summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-08-09 00:11:27 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2022-08-09 00:11:27 +0000
commit4d58268e5482283d736298c01e5efa5633ae04e1 (patch)
treea299d9a1593619e031c20163744b379e28d2eac3
parentd3fb07d5b10b01e24f33298252d854fc2c149786 (diff)
downloadgitlab-ce-4d58268e5482283d736298c01e5efa5633ae04e1.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/content_editor/components/content_editor.vue9
-rw-r--r--app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue15
-rw-r--r--app/controllers/concerns/product_analytics_tracking.rb31
-rw-r--r--app/controllers/projects/merge_requests/diffs_controller.rb4
-rw-r--r--app/models/integrations/jira.rb20
-rw-r--r--config/events/1658833247_integrations_class_perform_integrations_action.yml23
-rw-r--r--config/feature_flags/development/etag_merge_request_diff_batches.yml8
-rw-r--r--doc/development/database/batched_background_migrations.md17
-rw-r--r--doc/user/application_security/dependency_scanning/index.md3
-rw-r--r--doc/user/free_user_limit.md2
-rw-r--r--doc/user/project/repository/reducing_the_repo_size_using_git.md6
-rw-r--r--lib/gitlab/background_migration/batched_migration_job.rb8
-rw-r--r--lib/gitlab/database/migrations/batched_background_migration_helpers.rb5
-rw-r--r--spec/frontend/content_editor/components/content_editor_spec.js14
-rw-r--r--spec/frontend/pages/shared/wikis/components/wiki_form_spec.js32
-rw-r--r--spec/lib/gitlab/background_migration/batched_migration_job_spec.rb11
-rw-r--r--spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb117
-rw-r--r--spec/lib/gitlab/database/migrations/test_batched_background_runner_spec.rb13
-rw-r--r--spec/models/integrations/jira_spec.rb22
-rw-r--r--spec/requests/projects/merge_requests/diffs_spec.rb147
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