diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-08-09 00:11:27 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-08-09 00:11:27 +0000 |
commit | 4d58268e5482283d736298c01e5efa5633ae04e1 (patch) | |
tree | a299d9a1593619e031c20163744b379e28d2eac3 | |
parent | d3fb07d5b10b01e24f33298252d854fc2c149786 (diff) | |
download | gitlab-ce-4d58268e5482283d736298c01e5efa5633ae04e1.tar.gz |
Add latest changes from gitlab-org/gitlab@master
20 files changed, 431 insertions, 76 deletions
diff --git a/app/assets/javascripts/content_editor/components/content_editor.vue b/app/assets/javascripts/content_editor/components/content_editor.vue index 74ae37b6d06..c3c881d9135 100644 --- a/app/assets/javascripts/content_editor/components/content_editor.vue +++ b/app/assets/javascripts/content_editor/components/content_editor.vue @@ -84,7 +84,14 @@ export default { <template> <content-editor-provider :content-editor="contentEditor"> <div> - <editor-state-observer @docUpdate="notifyChange" @focus="focus" @blur="blur" /> + <editor-state-observer + @docUpdate="notifyChange" + @focus="focus" + @blur="blur" + @loading="$emit('loading')" + @loadingSuccess="$emit('loadingSuccess')" + @loadingError="$emit('loadingError')" + /> <content-editor-alert /> <div data-testid="content-editor" diff --git a/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue b/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue index 5576c6e2c62..9d7d9e376cf 100644 --- a/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue +++ b/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue @@ -117,6 +117,7 @@ export default { isDirty: false, contentEditorRenderFailed: false, contentEditorEmpty: false, + switchEditingControlDisabled: false, }; }, computed: { @@ -300,6 +301,14 @@ export default { }, }); }, + + enableSwitchEditingControl() { + this.switchEditingControlDisabled = false; + }, + + disableSwitchEditingControl() { + this.switchEditingControlDisabled = true; + }, }, }; </script> @@ -382,9 +391,10 @@ export default { <gl-segmented-control data-testid="toggle-editing-mode-button" data-qa-selector="editing_mode_button" - :checked="editingMode" class="gl-display-flex" + :checked="editingMode" :options="$options.switchEditingControlOptions" + :disabled="switchEditingControlDisabled" @input="toggleEditingMode" /> </div> @@ -428,6 +438,9 @@ export default { :uploads-path="pageInfo.uploadsPath" @initialized="loadInitialContent" @change="handleContentEditorChange" + @loading="disableSwitchEditingControl" + @loadingSuccess="enableSwitchEditingControl" + @loadingError="enableSwitchEditingControl" /> <input id="wiki_content" v-model.trim="content" type="hidden" name="wiki[content]" /> </div> diff --git a/app/controllers/concerns/product_analytics_tracking.rb b/app/controllers/concerns/product_analytics_tracking.rb index dc7ba8295b9..0582e40a2fe 100644 --- a/app/controllers/concerns/product_analytics_tracking.rb +++ b/app/controllers/concerns/product_analytics_tracking.rb @@ -13,6 +13,14 @@ module ProductAnalyticsTracking route_events_to(destinations, name, &block) end end + + def track_custom_event(*controller_actions, name:, conditions: nil, action:, label:, destinations: [:redis_hll], &block) + custom_conditions = [:trackable_html_request?, *conditions] + + after_action only: controller_actions, if: custom_conditions do + route_custom_events_to(destinations, name, action, label, &block) + end + end end private @@ -25,13 +33,34 @@ module ProductAnalyticsTracking end end + def route_custom_events_to(destinations, name, action, label, &block) + track_unique_redis_hll_event(name, &block) if destinations.include?(:redis_hll) + + return unless destinations.include?(:snowplow) && event_enabled?(name) + + optional_arguments = { + project: tracking_project_source + }.compact + + Gitlab::Tracking.event( + self.class.to_s, + action, + user: current_user, + property: name, + label: label, + namespace: tracking_namespace_source, + **optional_arguments + ) + end + def event_enabled?(event) events_to_ff = { g_analytics_valuestream: :route_hll_to_snowplow, i_search_paid: :route_hll_to_snowplow_phase2, i_search_total: :route_hll_to_snowplow_phase2, - i_search_advanced: :route_hll_to_snowplow_phase2 + i_search_advanced: :route_hll_to_snowplow_phase2, + i_ecosystem_jira_service_list_issues: :route_hll_to_snowplow_phase2 } Feature.enabled?(events_to_ff[event.to_sym], tracking_namespace_source) diff --git a/app/controllers/projects/merge_requests/diffs_controller.rb b/app/controllers/projects/merge_requests/diffs_controller.rb index 0dcc2bc3181..2b124aefd36 100644 --- a/app/controllers/projects/merge_requests/diffs_controller.rb +++ b/app/controllers/projects/merge_requests/diffs_controller.rb @@ -62,6 +62,10 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic options[:allow_tree_conflicts] ] + if Feature.enabled?(:etag_merge_request_diff_batches, @merge_request.project) + return unless stale?(etag: [cache_context, diffs]) + end + render_cached( diffs, with: PaginatedDiffSerializer.new(current_user: current_user), diff --git a/app/models/integrations/jira.rb b/app/models/integrations/jira.rb index 5f68f206e15..8759932bc62 100644 --- a/app/models/integrations/jira.rb +++ b/app/models/integrations/jira.rb @@ -18,6 +18,10 @@ module Integrations SECTION_TYPE_JIRA_TRIGGER = 'jira_trigger' SECTION_TYPE_JIRA_ISSUES = 'jira_issues' + SNOWPLOW_EVENT_CATEGORY = self.name + SNOWPLOW_EVENT_ACTION = 'perform_integrations_action' + SNOWPLOW_EVENT_LABEL = 'redis_hll_counters.ecosystem.ecosystem_total_unique_counts_monthly' + validates :url, public_url: true, presence: true, if: :activated? validates :api_url, public_url: true, allow_blank: true validates :username, presence: true, if: :activated? @@ -384,6 +388,22 @@ module Integrations key = "i_ecosystem_jira_service_#{action}" Gitlab::UsageDataCounters::HLLRedisCounter.track_event(key, values: user.id) + + return unless Feature.enabled?(:route_hll_to_snowplow_phase2) + + optional_arguments = { + project: project, + namespace: group || project&.namespace + }.compact + + Gitlab::Tracking.event( + SNOWPLOW_EVENT_CATEGORY, + SNOWPLOW_EVENT_ACTION, + label: SNOWPLOW_EVENT_LABEL, + property: key, + user: user, + **optional_arguments + ) end def add_issue_solved_comment(issue, commit_id, commit_url) diff --git a/config/events/1658833247_integrations_class_perform_integrations_action.yml b/config/events/1658833247_integrations_class_perform_integrations_action.yml new file mode 100644 index 00000000000..62da809fe14 --- /dev/null +++ b/config/events/1658833247_integrations_class_perform_integrations_action.yml @@ -0,0 +1,23 @@ +--- +description: Integration usage event +category: integrations class +action: perform_integrations_action +property_description: the name of the performed action +identifiers: +- project +- user +- namespace +product_section: dev +product_stage: ecosystem +product_group: integrations +product_category: integrations +milestone: "15.3" +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93468 +distributions: +- ce +- ee +tiers: +- free +- premium +- ultimate + diff --git a/config/feature_flags/development/etag_merge_request_diff_batches.yml b/config/feature_flags/development/etag_merge_request_diff_batches.yml new file mode 100644 index 00000000000..8cd3ba8637a --- /dev/null +++ b/config/feature_flags/development/etag_merge_request_diff_batches.yml @@ -0,0 +1,8 @@ +--- +name: etag_merge_request_diff_batches +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93953 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/369488 +milestone: '15.3' +type: development +group: group::code review +default_enabled: false diff --git a/doc/development/database/batched_background_migrations.md b/doc/development/database/batched_background_migrations.md index cfd24b54915..f267930f3da 100644 --- a/doc/development/database/batched_background_migrations.md +++ b/doc/development/database/batched_background_migrations.md @@ -105,11 +105,16 @@ for more details. ## Batched background migrations for EE-only features -All the background migration classes for EE-only features should be present in GitLab CE. -For this purpose, create an empty class for GitLab CE, and extend it for GitLab EE +All the background migration classes for EE-only features should be present in GitLab FOSS. +For this purpose, create an empty class for GitLab FOSS, and extend it for GitLab EE as explained in the guidelines for [implementing Enterprise Edition features](../ee_features.md#code-in-libgitlabbackground_migration). +NOTE: +Background migration classes for EE-only features that use job arguments should define them +in the GitLab FOSS class. This is required to prevent job arguments validation from failing when +migration is scheduled in GitLab FOSS context. + Batched Background migrations are simple classes that define a `perform` method. A Sidekiq worker then executes such a class, passing any arguments to it. All migration classes must be defined in the namespace @@ -132,6 +137,10 @@ queue_batched_background_migration( ) ``` +NOTE: +This helper raises an error if the number of provided job arguments does not match +the number of [job arguments](#job-arguments) defined in `JOB_CLASS_NAME`. + Make sure the newly-created data is either migrated, or saved in both the old and new version upon creation. Removals in turn can be handled by defining foreign keys with cascading deletes. @@ -201,6 +210,10 @@ queue_batched_background_migration( ) ``` +NOTE: +If the number of defined job arguments does not match the number of job arguments provided when +scheduling the migration, `queue_batched_background_migration` raises an error. + In this example, `copy_from` returns `name`, and `copy_to` returns `name_convert_to_text`: ```ruby diff --git a/doc/user/application_security/dependency_scanning/index.md b/doc/user/application_security/dependency_scanning/index.md index d3856c0c282..532698d28e3 100644 --- a/doc/user/application_security/dependency_scanning/index.md +++ b/doc/user/application_security/dependency_scanning/index.md @@ -924,8 +924,7 @@ Please check the [Release Process documentation](https://gitlab.com/gitlab-org/s ## Contributing to the vulnerability database -You can search the [`gemnasium-db`](https://gitlab.com/gitlab-org/security-products/gemnasium-db) project -to find a vulnerability in the GitLab Advisory Database. +To find a vulnerability, you can search the [`GitLab Advisory Database`](https://advisories.gitlab.com/). You can also [submit new vulnerabilities](https://gitlab.com/gitlab-org/security-products/gemnasium-db/blob/master/CONTRIBUTING.md). ## Running dependency scanning in an offline environment diff --git a/doc/user/free_user_limit.md b/doc/user/free_user_limit.md index 46ed6785d65..a62b9c9e363 100644 --- a/doc/user/free_user_limit.md +++ b/doc/user/free_user_limit.md @@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Free user limit **(FREE SAAS)** -From September 15, 2022, namespaces in GitLab.com on the Free tier +From October 19, 2022, namespaces in GitLab.com on the Free tier will be limited to five (5) members per [namespace](namespace/index.md). This limit applies to top-level groups and personal namespaces. diff --git a/doc/user/project/repository/reducing_the_repo_size_using_git.md b/doc/user/project/repository/reducing_the_repo_size_using_git.md index 4e948bcc9ae..344c288b607 100644 --- a/doc/user/project/repository/reducing_the_repo_size_using_git.md +++ b/doc/user/project/repository/reducing_the_repo_size_using_git.md @@ -195,8 +195,8 @@ When using repository cleanup, note: - Project statistics are cached. You may need to wait 5-10 minutes to see a reduction in storage utilization. - The cleanup prunes loose objects older than 30 minutes. This means objects added or referenced in the last 30 minutes - are not be removed immediately. If you have access to the - [Gitaly](../../../administration/gitaly/index.md) server, you may slip that delay and run `git gc --prune=now` to + are not removed immediately. If you have access to the + [Gitaly](../../../administration/gitaly/index.md) server, you may skip that delay and run `git gc --prune=now` to prune all loose objects immediately. - This process removes some copies of the rewritten commits from the GitLab cache and database, but there are still numerous gaps in coverage and some of the copies may persist indefinitely. @@ -207,7 +207,7 @@ When using repository cleanup, note: Repository size limits: -- Can [be set by an administrator](../../admin_area/settings/account_and_limit_settings.md#account-and-limit-settings) +- Can [be set by an administrator](../../admin_area/settings/account_and_limit_settings.md#account-and-limit-settings). - Can [be set by an administrator](../../admin_area/settings/account_and_limit_settings.md) on self-managed instances. - Are [set for GitLab.com](../../gitlab_com/index.md#account-and-limit-settings). diff --git a/lib/gitlab/background_migration/batched_migration_job.rb b/lib/gitlab/background_migration/batched_migration_job.rb index 711c6ac35a9..dedcdf5d745 100644 --- a/lib/gitlab/background_migration/batched_migration_job.rb +++ b/lib/gitlab/background_migration/batched_migration_job.rb @@ -24,12 +24,20 @@ module Gitlab @connection = connection end + def self.job_arguments_count + 0 + end + def self.job_arguments(*args) args.each.with_index do |arg, index| define_method(arg) do @job_arguments[index] end end + + define_singleton_method(:job_arguments_count) do + args.count + end end def perform diff --git a/lib/gitlab/database/migrations/batched_background_migration_helpers.rb b/lib/gitlab/database/migrations/batched_background_migration_helpers.rb index 936b986ea07..ba5132326f6 100644 --- a/lib/gitlab/database/migrations/batched_background_migration_helpers.rb +++ b/lib/gitlab/database/migrations/batched_background_migration_helpers.rb @@ -107,6 +107,11 @@ module Gitlab status_event: status_event ) + if migration.job_class.respond_to?(:job_arguments_count) && migration.job_class.job_arguments_count != job_arguments.count + raise "Wrong number of job arguments for #{migration.job_class_name} " \ + "(given #{job_arguments.count}, expected #{migration.job_class.job_arguments_count})" + end + # Below `BatchedMigration` attributes were introduced after the # initial `batched_background_migrations` table was created, so any # migrations that ran relying on initial table schema would not know diff --git a/spec/frontend/content_editor/components/content_editor_spec.js b/spec/frontend/content_editor/components/content_editor_spec.js index 9ee3b017831..0ba2672100b 100644 --- a/spec/frontend/content_editor/components/content_editor_spec.js +++ b/spec/frontend/content_editor/components/content_editor_spec.js @@ -19,6 +19,7 @@ describe('ContentEditor', () => { const findEditorElement = () => wrapper.findByTestId('content-editor'); const findEditorContent = () => wrapper.findComponent(EditorContent); + const findEditorStateObserver = () => wrapper.findComponent(EditorStateObserver); const createWrapper = (propsData = {}) => { renderMarkdown = jest.fn(); @@ -119,4 +120,17 @@ describe('ContentEditor', () => { expect(wrapper.findComponent(FormattingBubbleMenu).exists()).toBe(true); }); + + it.each` + event + ${'loading'} + ${'loadingSuccess'} + ${'loadingError'} + `('broadcasts $event event triggered by editor-state-observer component', ({ event }) => { + createWrapper(); + + findEditorStateObserver().vm.$emit(event); + + expect(wrapper.emitted(event)).toHaveLength(1); + }); }); diff --git a/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js b/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js index 160e0832d35..204c48f8de1 100644 --- a/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js +++ b/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js @@ -392,6 +392,38 @@ describe('WikiForm', () => { expect(findContent().element.value).toBe(contentEditorFakeSerializedContent); }); }); + + describe('when content editor is loading', () => { + beforeEach(async () => { + findContentEditor().vm.$emit('loading'); + + await nextTick(); + }); + + it('disables toggle editing mode button', () => { + expect(findToggleEditingModeButton().attributes().disabled).toBe('true'); + }); + + describe('when content editor loads successfully', () => { + it('enables toggle editing mode button', async () => { + findContentEditor().vm.$emit('loadingSuccess'); + + await nextTick(); + + expect(findToggleEditingModeButton().attributes().disabled).not.toBeDefined(); + }); + }); + + describe('when content editor fails to load', () => { + it('enables toggle editing mode button', async () => { + findContentEditor().vm.$emit('loadingError'); + + await nextTick(); + + expect(findToggleEditingModeButton().attributes().disabled).not.toBeDefined(); + }); + }); + }); }); }); diff --git a/spec/lib/gitlab/background_migration/batched_migration_job_spec.rb b/spec/lib/gitlab/background_migration/batched_migration_job_spec.rb index 859186abc60..6b6ee148bbf 100644 --- a/spec/lib/gitlab/background_migration/batched_migration_job_spec.rb +++ b/spec/lib/gitlab/background_migration/batched_migration_job_spec.rb @@ -25,6 +25,17 @@ RSpec.describe Gitlab::BackgroundMigration::BatchedMigrationJob do it 'defines methods' do expect(job_instance.value_a).to eq('a') expect(job_instance.value_b).to eq('b') + expect(job_class.job_arguments_count).to eq(2) + end + + context 'when no job arguments are defined' do + let(:job_class) do + Class.new(described_class) + end + + it 'job_arguments_count is 0' do + expect(job_class.job_arguments_count).to eq(0) + end end end diff --git a/spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb b/spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb index 5bfb2516ba1..a2f6e6b43ed 100644 --- a/spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb +++ b/spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb @@ -15,12 +15,25 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d describe '#queue_batched_background_migration' do let(:pgclass_info) { instance_double('Gitlab::Database::PgClass', cardinality_estimate: 42) } + let(:job_class) do + Class.new(Gitlab::BackgroundMigration::BatchedMigrationJob) do + def self.name + 'MyJobClass' + end + end + end before do allow(Gitlab::Database::PgClass).to receive(:for_table).and_call_original expect(Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas).to receive(:require_dml_mode!) allow(migration).to receive(:transaction_open?).and_return(false) + + stub_const("Gitlab::Database::BackgroundMigration::BatchedMigration::JOB_CLASS_MODULE", '') + allow_next_instance_of(Gitlab::Database::BackgroundMigration::BatchedMigration) do |batched_migration| + allow(batched_migration).to receive(:job_class) + .and_return(job_class) + end end context 'when such migration already exists' do @@ -42,7 +55,7 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d expect do migration.queue_batched_background_migration( - 'MyJobClass', + job_class.name, :projects, :id, [:id], [:id_convert_to_bigint], @@ -62,7 +75,7 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d expect do migration.queue_batched_background_migration( - 'MyJobClass', + job_class.name, :projects, :id, job_interval: 5.minutes, @@ -97,7 +110,7 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d it 'sets the job interval to the minimum value' do expect do - migration.queue_batched_background_migration('MyJobClass', :events, :id, job_interval: minimum_delay - 1.minute) + migration.queue_batched_background_migration(job_class.name, :events, :id, job_interval: minimum_delay - 1.minute) end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1) created_migration = Gitlab::Database::BackgroundMigration::BatchedMigration.last @@ -107,26 +120,76 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d end context 'when additional arguments are passed to the method' do - it 'saves the arguments on the database record' do - expect do - migration.queue_batched_background_migration( - 'MyJobClass', - :projects, - :id, - 'my', - 'arguments', - job_interval: 5.minutes, - batch_max_value: 1000) - end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1) + context 'when the job class provides job_arguments_count' do + context 'when defined job arguments for the job class does not match provided arguments' do + it 'raises an error' do + expect do + migration.queue_batched_background_migration( + job_class.name, + :projects, + :id, + 'my', + 'arguments', + job_interval: 2.minutes) + end.to raise_error(RuntimeError, /Wrong number of job arguments for MyJobClass \(given 2, expected 0\)/) + end + end - expect(Gitlab::Database::BackgroundMigration::BatchedMigration.last).to have_attributes( - job_class_name: 'MyJobClass', - table_name: 'projects', - column_name: 'id', - interval: 300, - min_value: 1, - max_value: 1000, - job_arguments: %w[my arguments]) + context 'when defined job arguments for the job class match provided arguments' do + let(:job_class) do + Class.new(Gitlab::BackgroundMigration::BatchedMigrationJob) do + def self.name + 'MyJobClass' + end + + job_arguments :foo, :bar + end + end + + it 'saves the arguments on the database record' do + expect do + migration.queue_batched_background_migration( + job_class.name, + :projects, + :id, + 'my', + 'arguments', + job_interval: 5.minutes, + batch_max_value: 1000) + end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1) + + expect(Gitlab::Database::BackgroundMigration::BatchedMigration.last).to have_attributes( + job_class_name: 'MyJobClass', + table_name: 'projects', + column_name: 'id', + interval: 300, + min_value: 1, + max_value: 1000, + job_arguments: %w[my arguments]) + end + end + end + + context 'when the job class does not provide job_arguments_count' do + let(:job_class) do + Class.new do + def self.name + 'MyJobClass' + end + end + end + + it 'does not raise an error' do + expect do + migration.queue_batched_background_migration( + job_class.name, + :projects, + :id, + 'my', + 'arguments', + job_interval: 2.minutes) + end.not_to raise_error + end end end @@ -138,7 +201,7 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d it 'creates the record with the current max value' do expect do - migration.queue_batched_background_migration('MyJobClass', :events, :id, job_interval: 5.minutes) + migration.queue_batched_background_migration(job_class.name, :events, :id, job_interval: 5.minutes) end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1) created_migration = Gitlab::Database::BackgroundMigration::BatchedMigration.last @@ -148,7 +211,7 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d it 'creates the record with an active status' do expect do - migration.queue_batched_background_migration('MyJobClass', :events, :id, job_interval: 5.minutes) + migration.queue_batched_background_migration(job_class.name, :events, :id, job_interval: 5.minutes) end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1) expect(Gitlab::Database::BackgroundMigration::BatchedMigration.last).to be_active @@ -158,7 +221,7 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d context 'when the database is empty' do it 'sets the max value to the min value' do expect do - migration.queue_batched_background_migration('MyJobClass', :events, :id, job_interval: 5.minutes) + migration.queue_batched_background_migration(job_class.name, :events, :id, job_interval: 5.minutes) end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1) created_migration = Gitlab::Database::BackgroundMigration::BatchedMigration.last @@ -168,7 +231,7 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d it 'creates the record with a finished status' do expect do - migration.queue_batched_background_migration('MyJobClass', :projects, :id, job_interval: 5.minutes) + migration.queue_batched_background_migration(job_class.name, :projects, :id, job_interval: 5.minutes) end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1) expect(Gitlab::Database::BackgroundMigration::BatchedMigration.last).to be_finished @@ -181,7 +244,7 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d expect(migration).to receive(:gitlab_schema_from_context).and_return(:gitlab_ci) expect do - migration.queue_batched_background_migration('MyJobClass', :events, :id, job_interval: 5.minutes) + migration.queue_batched_background_migration(job_class.name, :events, :id, job_interval: 5.minutes) end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1) created_migration = Gitlab::Database::BackgroundMigration::BatchedMigration.last diff --git a/spec/lib/gitlab/database/migrations/test_batched_background_runner_spec.rb b/spec/lib/gitlab/database/migrations/test_batched_background_runner_spec.rb index 4a49f0224f0..9451a6bd34a 100644 --- a/spec/lib/gitlab/database/migrations/test_batched_background_runner_spec.rb +++ b/spec/lib/gitlab/database/migrations/test_batched_background_runner_spec.rb @@ -50,18 +50,16 @@ RSpec.describe Gitlab::Database::Migrations::TestBatchedBackgroundRunner, :freez context 'with jobs to run' do let(:migration_name) { 'TestBackgroundMigration' } - before do - migration.queue_batched_background_migration( - migration_name, table_name, :id, job_interval: 5.minutes, batch_size: 100 - ) - end - it 'samples jobs' do calls = [] define_background_migration(migration_name) do |*args| calls << args end + migration.queue_batched_background_migration(migration_name, table_name, :id, + job_interval: 5.minutes, + batch_size: 100) + described_class.new(result_dir: result_dir, connection: connection).run_jobs(for_duration: 3.minutes) expect(calls.count).to eq(10) # 1000 rows / batch size 100 = 10 @@ -70,6 +68,9 @@ RSpec.describe Gitlab::Database::Migrations::TestBatchedBackgroundRunner, :freez context 'with multiple jobs to run' do it 'runs all jobs created within the last 3 hours' do old_migration = define_background_migration(migration_name) + migration.queue_batched_background_migration(migration_name, table_name, :id, + job_interval: 5.minutes, + batch_size: 100) travel 4.hours diff --git a/spec/models/integrations/jira_spec.rb b/spec/models/integrations/jira_spec.rb index 01c08a0948f..a52a4514ebe 100644 --- a/spec/models/integrations/jira_spec.rb +++ b/spec/models/integrations/jira_spec.rb @@ -619,6 +619,18 @@ RSpec.describe Integrations::Jira do close_issue end + it_behaves_like 'Snowplow event tracking' do + subject { close_issue } + + let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } + let(:category) { 'Integrations::Jira' } + let(:action) { 'perform_integrations_action' } + let(:namespace) { project.namespace } + let(:user) { current_user } + let(:label) { 'redis_hll_counters.ecosystem.ecosystem_total_unique_counts_monthly' } + let(:property) { 'i_ecosystem_jira_service_close_issue' } + end + it 'does not fail if remote_link.all on issue returns nil' do allow(JIRA::Resource::Remotelink).to receive(:all).and_return(nil) @@ -962,6 +974,16 @@ RSpec.describe Integrations::Jira do subject end + + it_behaves_like 'Snowplow event tracking' do + let(:feature_flag_name) { :route_hll_to_snowplow_phase2 } + let(:category) { 'Integrations::Jira' } + let(:action) { 'perform_integrations_action' } + let(:namespace) { project.namespace } + let(:user) { current_user } + let(:label) { 'redis_hll_counters.ecosystem.ecosystem_total_unique_counts_monthly' } + let(:property) { 'i_ecosystem_jira_service_cross_reference' } + end end context 'for commits' do diff --git a/spec/requests/projects/merge_requests/diffs_spec.rb b/spec/requests/projects/merge_requests/diffs_spec.rb index e17be1ff984..4e6a7be415e 100644 --- a/spec/requests/projects/merge_requests/diffs_spec.rb +++ b/spec/requests/projects/merge_requests/diffs_spec.rb @@ -13,8 +13,6 @@ RSpec.describe 'Merge Requests Diffs' do end describe 'GET diffs_batch' do - let(:headers) { {} } - shared_examples_for 'serializes diffs with expected arguments' do it 'serializes paginated merge request diff collection' do expect_next_instance_of(PaginatedDiffSerializer) do |instance| @@ -24,6 +22,8 @@ RSpec.describe 'Merge Requests Diffs' do end subject + + expect(response).to have_gitlab_http_status(:success) end end @@ -40,7 +40,7 @@ RSpec.describe 'Merge Requests Diffs' do } end - def go(extra_params = {}) + def go(headers: {}, **extra_params) params = { namespace_id: project.namespace.to_param, project_id: project, @@ -54,13 +54,15 @@ RSpec.describe 'Merge Requests Diffs' do end context 'with caching', :use_clean_rails_memory_store_caching do - subject { go(page: 0, per_page: 5) } + subject { go(headers: headers, page: 0, per_page: 5) } + + let(:headers) { {} } context 'when the request has not been cached' do - it_behaves_like 'serializes diffs with expected arguments' do - let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } - let(:expected_options) { collection_arguments(total_pages: 20) } - end + let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } + let(:expected_options) { collection_arguments(total_pages: 20) } + + it_behaves_like 'serializes diffs with expected arguments' end context 'when the request has already been cached' do @@ -76,21 +78,61 @@ RSpec.describe 'Merge Requests Diffs' do subject end + context 'when using ETags' do + context 'when etag_merge_request_diff_batches is true' do + let(:headers) { { 'If-None-Match' => response.etag } } + + it 'does not serialize diffs' do + expect(PaginatedDiffSerializer).not_to receive(:new) + + go(headers: headers, page: 0, per_page: 5) + + expect(response).to have_gitlab_http_status(:not_modified) + end + end + + context 'when etag_merge_request_diff_batches is false' do + let(:headers) { { 'If-None-Match' => response.etag } } + + before do + stub_feature_flags(etag_merge_request_diff_batches: false) + end + + it 'does not serialize diffs' do + expect_next_instance_of(PaginatedDiffSerializer) do |instance| + expect(instance).not_to receive(:represent) + end + + subject + + expect(response).to have_gitlab_http_status(:success) + end + end + end + context 'with the different user' do let(:another_user) { create(:user) } + let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } + let(:expected_options) { collection_arguments(total_pages: 20) } before do project.add_maintainer(another_user) sign_in(another_user) end - it_behaves_like 'serializes diffs with expected arguments' do - let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } - let(:expected_options) { collection_arguments(total_pages: 20) } + it_behaves_like 'serializes diffs with expected arguments' + + context 'when using ETag caching' do + it_behaves_like 'serializes diffs with expected arguments' do + let(:headers) { { 'If-None-Match' => response.etag } } + end end end context 'with a new unfoldable diff position' do + let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } + let(:expected_options) { collection_arguments(total_pages: 20) } + let(:unfoldable_position) do create(:diff_position) end @@ -103,69 +145,108 @@ RSpec.describe 'Merge Requests Diffs' do end end - it_behaves_like 'serializes diffs with expected arguments' do - let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } - let(:expected_options) { collection_arguments(total_pages: 20) } + it_behaves_like 'serializes diffs with expected arguments' + + context 'when using ETag caching' do + it_behaves_like 'serializes diffs with expected arguments' do + let(:headers) { { 'If-None-Match' => response.etag } } + end end end context 'with disabled display_merge_conflicts_in_diff feature' do + let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } + let(:expected_options) { collection_arguments(total_pages: 20).merge(allow_tree_conflicts: false) } + before do stub_feature_flags(display_merge_conflicts_in_diff: false) end - it_behaves_like 'serializes diffs with expected arguments' do - let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } - let(:expected_options) { collection_arguments(total_pages: 20).merge(allow_tree_conflicts: false) } + it_behaves_like 'serializes diffs with expected arguments' + + context 'when using ETag caching' do + it_behaves_like 'serializes diffs with expected arguments' do + let(:headers) { { 'If-None-Match' => response.etag } } + end end end context 'with diff_head option' do subject { go(page: 0, per_page: 5, diff_head: true) } + let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } + let(:expected_options) { collection_arguments(total_pages: 20).merge(merge_ref_head_diff: true) } + before do merge_request.create_merge_head_diff! end - it_behaves_like 'serializes diffs with expected arguments' do - let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } - let(:expected_options) { collection_arguments(total_pages: 20).merge(merge_ref_head_diff: true) } + it_behaves_like 'serializes diffs with expected arguments' + + context 'when using ETag caching' do + it_behaves_like 'serializes diffs with expected arguments' do + let(:headers) { { 'If-None-Match' => response.etag } } + end end end context 'with the different pagination option' do subject { go(page: 5, per_page: 5) } - it_behaves_like 'serializes diffs with expected arguments' do - let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } - let(:expected_options) { collection_arguments(total_pages: 20) } + let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } + let(:expected_options) { collection_arguments(total_pages: 20) } + + it_behaves_like 'serializes diffs with expected arguments' + + context 'when using ETag caching' do + it_behaves_like 'serializes diffs with expected arguments' do + let(:headers) { { 'If-None-Match' => response.etag } } + end end end context 'with the different diff_view' do subject { go(page: 0, per_page: 5, view: :parallel) } - it_behaves_like 'serializes diffs with expected arguments' do - let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } - let(:expected_options) { collection_arguments(total_pages: 20).merge(diff_view: :parallel) } + let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } + let(:expected_options) { collection_arguments(total_pages: 20).merge(diff_view: :parallel) } + + it_behaves_like 'serializes diffs with expected arguments' + + context 'when using ETag caching' do + it_behaves_like 'serializes diffs with expected arguments' do + let(:headers) { { 'If-None-Match' => response.etag } } + end end end context 'with the different expanded option' do subject { go(page: 0, per_page: 5, expanded: true ) } - it_behaves_like 'serializes diffs with expected arguments' do - let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } - let(:expected_options) { collection_arguments(total_pages: 20) } + let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch } + let(:expected_options) { collection_arguments(total_pages: 20) } + + it_behaves_like 'serializes diffs with expected arguments' + + context 'when using ETag caching' do + it_behaves_like 'serializes diffs with expected arguments' do + let(:headers) { { 'If-None-Match' => response.etag } } + end end end context 'with the different ignore_whitespace_change option' do subject { go(page: 0, per_page: 5, w: 1) } - it_behaves_like 'serializes diffs with expected arguments' do - let(:collection) { Gitlab::Diff::FileCollection::Compare } - let(:expected_options) { collection_arguments(total_pages: 20) } + let(:collection) { Gitlab::Diff::FileCollection::Compare } + let(:expected_options) { collection_arguments(total_pages: 20) } + + it_behaves_like 'serializes diffs with expected arguments' + + context 'when using ETag caching' do + it_behaves_like 'serializes diffs with expected arguments' do + let(:headers) { { 'If-None-Match' => response.etag } } + end end end end @@ -177,6 +258,8 @@ RSpec.describe 'Merge Requests Diffs' do expect(Rails.cache).not_to receive(:fetch).with(/cache:gitlab:PaginatedDiffSerializer/).and_call_original subject + + expect(response).to have_gitlab_http_status(:success) end end end |