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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-05-26 09:08:37 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-05-26 09:08:37 +0300
commit864dae0d98424b463501c21eda1b633c14956fa9 (patch)
tree9340f7dad0a32f7e8c8a3b5ad723fbf0de26c3ba
parent47ef8c6c530ee1cac0e1046b098755ec949da894 (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.gitpod.yml6
-rw-r--r--app/assets/javascripts/work_items/components/work_item_detail.vue2
-rw-r--r--app/assets/javascripts/work_items/components/work_item_links/work_item_links.vue6
-rw-r--r--app/controllers/projects/work_items_controller.rb1
-rw-r--r--app/models/ci/bridge.rb22
-rw-r--r--app/workers/all_queues.yml18
-rw-r--r--app/workers/issue_placement_worker.rb71
-rw-r--r--app/workers/issue_rebalancing_worker.rb56
-rw-r--r--config/feature_flags/development/work_items_hierarchy.yml (renamed from config/feature_flags/development/ci_trigger_forward_variables.yml)12
-rw-r--r--config/sidekiq_queues.yml4
-rw-r--r--doc/administration/gitaly/monitoring.md1
-rw-r--r--doc/ci/yaml/index.md9
-rw-r--r--doc/development/testing_guide/best_practices.md33
-rw-r--r--doc/user/group/saml_sso/index.md13
-rw-r--r--locale/gitlab.pot6
-rw-r--r--qa/qa/specs/features/api/4_verify/api_variable_inheritance_with_forward_pipeline_variables_spec.rb8
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/ci_variable/ui_variable_inheritable_when_forward_pipeline_variables_true_spec.rb8
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/ci_variable/ui_variable_non_inheritable_when_forward_pipeline_variables_false_spec.rb8
-rw-r--r--qa/qa/specs/features/shared_contexts/variable_inheritance_shared_context.rb2
-rw-r--r--spec/factories/ci/builds.rb6
-rw-r--r--spec/factories/clusters/applications/helm.rb13
-rw-r--r--spec/factories/commits.rb9
-rw-r--r--spec/factories/container_repositories.rb9
-rw-r--r--spec/factories/deployments.rb2
-rw-r--r--spec/factories/merge_requests.rb2
-rw-r--r--spec/factories/projects.rb4
-rw-r--r--spec/helpers/routing/pseudonymization_helper_spec.rb3
-rw-r--r--spec/lib/gitlab/ci/status/build/play_spec.rb7
-rw-r--r--spec/lib/gitlab/ci/status/build/scheduled_spec.rb5
-rw-r--r--spec/models/ci/bridge_spec.rb33
-rw-r--r--spec/support/factory_bot.rb1
-rw-r--r--spec/support/helpers/stub_method_calls.rb66
-rw-r--r--spec/support_specs/helpers/stub_method_calls_spec.rb107
-rw-r--r--spec/workers/every_sidekiq_worker_spec.rb2
-rw-r--r--spec/workers/issue_placement_worker_spec.rb151
-rw-r--r--spec/workers/issue_rebalancing_worker_spec.rb104
37 files changed, 289 insertions, 523 deletions
diff --git a/.gitpod.yml b/.gitpod.yml
index 639fe4352e0..96c4eafd0e4 100644
--- a/.gitpod.yml
+++ b/.gitpod.yml
@@ -11,10 +11,8 @@ tasks:
(
set -e
cd /workspace/gitlab-development-kit
- # GitLab FOSS
- [[ -d /workspace/gitlab-foss ]] && ln -fs /workspace/gitlab-foss /workspace/gitlab-development-kit/gitlab
- # GitLab
- [[ -d /workspace/gitlab ]] && ln -fs /workspace/gitlab /workspace/gitlab-development-kit/gitlab
+ # Ensure GitLab directory is symlinked under the GDK
+ ln -nfs "$GITPOD_REPO_ROOT" /workspace/gitlab-development-kit/gitlab
mv /workspace/gitlab-development-kit/secrets.yml /workspace/gitlab-development-kit/gitlab/config
# ensure gdk.yml has correct instance settings
gdk config set gitlab.rails.port 443
diff --git a/app/assets/javascripts/work_items/components/work_item_detail.vue b/app/assets/javascripts/work_items/components/work_item_detail.vue
index 418c465d820..0d588746362 100644
--- a/app/assets/javascripts/work_items/components/work_item_detail.vue
+++ b/app/assets/javascripts/work_items/components/work_item_detail.vue
@@ -121,7 +121,7 @@ export default {
@error="error = $event"
@updated="$emit('workItemUpdated')"
/>
- <work-item-links :work-item-id="workItem.id" />
+ <work-item-links v-if="glFeatures.workItemsHierarchy" :work-item-id="workItem.id" />
</template>
</section>
</template>
diff --git a/app/assets/javascripts/work_items/components/work_item_links/work_item_links.vue b/app/assets/javascripts/work_items/components/work_item_links/work_item_links.vue
index 6124e669cb3..df3326083af 100644
--- a/app/assets/javascripts/work_items/components/work_item_links/work_item_links.vue
+++ b/app/assets/javascripts/work_items/components/work_item_links/work_item_links.vue
@@ -30,6 +30,11 @@ export default {
toggleIcon() {
return this.isOpen ? 'angle-up' : 'angle-down';
},
+ toggleLabel() {
+ return this.isOpen
+ ? s__('WorkItem|Collapse child items')
+ : s__('WorkItem|Expand child items');
+ },
},
methods: {
toggle() {
@@ -60,6 +65,7 @@ export default {
<gl-button
category="tertiary"
:icon="toggleIcon"
+ :aria-label="toggleLabel"
data-testid="toggle-links"
@click="toggle"
/>
diff --git a/app/controllers/projects/work_items_controller.rb b/app/controllers/projects/work_items_controller.rb
index de3168dd415..6db83a19d43 100644
--- a/app/controllers/projects/work_items_controller.rb
+++ b/app/controllers/projects/work_items_controller.rb
@@ -4,6 +4,7 @@ class Projects::WorkItemsController < Projects::ApplicationController
before_action do
push_force_frontend_feature_flag(:work_items, project&.work_items_feature_flag_enabled?)
push_frontend_feature_flag(:work_item_assignees)
+ push_frontend_feature_flag(:work_items_hierarchy, project)
end
feature_category :team_planning
diff --git a/app/models/ci/bridge.rb b/app/models/ci/bridge.rb
index a06b920342c..13af5b1f8d1 100644
--- a/app/models/ci/bridge.rb
+++ b/app/models/ci/bridge.rb
@@ -215,14 +215,10 @@ module Ci
end
def downstream_variables
- if ::Feature.enabled?(:ci_trigger_forward_variables, project)
- calculate_downstream_variables
- .reverse # variables priority
- .uniq { |var| var[:key] } # only one variable key to pass
- .reverse
- else
- legacy_downstream_variables
- end
+ calculate_downstream_variables
+ .reverse # variables priority
+ .uniq { |var| var[:key] } # only one variable key to pass
+ .reverse
end
def target_revision_ref
@@ -268,16 +264,6 @@ module Ci
}
end
- def legacy_downstream_variables
- variables = scoped_variables.concat(pipeline.persisted_variables)
-
- variables.to_runner_variables.yield_self do |all_variables|
- yaml_variables.to_a.map do |hash|
- { key: hash[:key], value: ::ExpandVariables.expand(hash[:value], all_variables) }
- end
- end
- end
-
def calculate_downstream_variables
expand_variables = scoped_variables
.concat(pipeline.persisted_variables)
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index c2836c04a4d..475a65f3399 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -2416,24 +2416,6 @@
:weight: 1
:idempotent: true
:tags: []
-- :name: issue_placement
- :worker_name: IssuePlacementWorker
- :feature_category: :team_planning
- :has_external_dependencies:
- :urgency: :high
- :resource_boundary: :cpu
- :weight: 2
- :idempotent: true
- :tags: []
-- :name: issue_rebalancing
- :worker_name: IssueRebalancingWorker
- :feature_category: :team_planning
- :has_external_dependencies:
- :urgency: :low
- :resource_boundary: :unknown
- :weight: 1
- :idempotent: true
- :tags: []
- :name: issues_placement
:worker_name: Issues::PlacementWorker
:feature_category: :team_planning
diff --git a/app/workers/issue_placement_worker.rb b/app/workers/issue_placement_worker.rb
deleted file mode 100644
index 26dec221f45..00000000000
--- a/app/workers/issue_placement_worker.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-# frozen_string_literal: true
-
-# DEPRECATED. Will be removed in 14.7 https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72803
-# Please use Issues::PlacementWorker instead
-#
-# todo: remove this worker and it's queue definition from all_queues after Issues::PlacementWorker is deployed
-# We want to keep it for one release in case some jobs are already scheduled in the old queue so we need the worker
-# to be available to finish those. All new jobs will be queued into the new queue.
-class IssuePlacementWorker
- include ApplicationWorker
-
- data_consistency :always
-
- sidekiq_options retry: 3
-
- idempotent!
- deduplicate :until_executed, including_scheduled: true
- feature_category :team_planning
- urgency :high
- worker_resource_boundary :cpu
- weight 2
-
- # Move at most the most recent 100 issues
- QUERY_LIMIT = 100
-
- # rubocop: disable CodeReuse/ActiveRecord
- def perform(issue_id, project_id = nil)
- issue = find_issue(issue_id, project_id)
- return unless issue
-
- # Temporary disable moving null elements because of performance problems
- # For more information check https://gitlab.com/gitlab-com/gl-infra/production/-/issues/4321
- return if issue.blocked_for_repositioning?
-
- # Move the oldest 100 unpositioned items to the end.
- # This is to deal with out-of-order execution of the worker,
- # while preserving creation order.
- to_place = Issue
- .relative_positioning_query_base(issue)
- .with_null_relative_position
- .order({ created_at: :asc }, { id: :asc })
- .limit(QUERY_LIMIT + 1)
- .to_a
-
- leftover = to_place.pop if to_place.count > QUERY_LIMIT
-
- Issue.move_nulls_to_end(to_place)
- Issues::BaseService.new(project: nil).rebalance_if_needed(to_place.max_by(&:relative_position))
- Issues::PlacementWorker.perform_async(nil, leftover.project_id) if leftover.present?
- rescue RelativePositioning::NoSpaceLeft => e
- Gitlab::ErrorTracking.log_exception(e, issue_id: issue_id, project_id: project_id)
- Issues::RebalancingWorker.perform_async(nil, *root_namespace_id_to_rebalance(issue, project_id))
- end
-
- def find_issue(issue_id, project_id)
- return Issue.id_in(issue_id).take if issue_id
-
- project = Project.id_in(project_id).take
- return unless project
-
- project.issues.take
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- private
-
- def root_namespace_id_to_rebalance(issue, project_id)
- project_id = project_id.presence || issue.project_id
- Project.find(project_id)&.self_or_root_group_ids
- end
-end
diff --git a/app/workers/issue_rebalancing_worker.rb b/app/workers/issue_rebalancing_worker.rb
deleted file mode 100644
index 73edb2eb653..00000000000
--- a/app/workers/issue_rebalancing_worker.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-# frozen_string_literal: true
-
-# DEPRECATED. Will be removed in 14.7 https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72803
-# Please use Issues::RebalancingWorker instead
-#
-# todo: remove this worker and it's queue definition from all_queues after Issue::RebalancingWorker is released.
-# We want to keep it for one release in case some jobs are already scheduled in the old queue so we need the worker
-# to be available to finish those. All new jobs will be queued into the new queue.
-class IssueRebalancingWorker
- include ApplicationWorker
-
- data_consistency :always
-
- sidekiq_options retry: 3
-
- idempotent!
- urgency :low
- feature_category :team_planning
- deduplicate :until_executed, including_scheduled: true
-
- def perform(ignore = nil, project_id = nil, root_namespace_id = nil)
- # we need to have exactly one of the project_id and root_namespace_id params be non-nil
- raise ArgumentError, "Expected only one of the params project_id: #{project_id} and root_namespace_id: #{root_namespace_id}" if project_id && root_namespace_id
- return if project_id.nil? && root_namespace_id.nil?
- return if ::Gitlab::Issues::Rebalancing::State.rebalance_recently_finished?(project_id, root_namespace_id)
-
- # pull the projects collection to be rebalanced either the project if namespace is not a group(i.e. user namesapce)
- # or the root namespace, this also makes the worker backward compatible with previous version where a project_id was
- # passed as the param
- projects_to_rebalance = projects_collection(project_id, root_namespace_id)
-
- # something might have happened with the namespace between scheduling the worker and actually running it,
- # maybe it was removed.
- if projects_to_rebalance.blank?
- Gitlab::ErrorTracking.log_exception(
- ArgumentError.new("Projects to be rebalanced not found for arguments: project_id #{project_id}, root_namespace_id: #{root_namespace_id}"),
- { project_id: project_id, root_namespace_id: root_namespace_id })
-
- return
- end
-
- Issues::RelativePositionRebalancingService.new(projects_to_rebalance).execute
- rescue Issues::RelativePositionRebalancingService::TooManyConcurrentRebalances => e
- Gitlab::ErrorTracking.log_exception(e, root_namespace_id: root_namespace_id, project_id: project_id)
- end
-
- private
-
- def projects_collection(project_id, root_namespace_id)
- # we can have either project_id(older version) or project_id if project is part of a user namespace and not a group
- # or root_namespace_id(newer version) never both.
- return Project.id_in([project_id]) if project_id
-
- Namespace.find_by_id(root_namespace_id)&.all_projects
- end
-end
diff --git a/config/feature_flags/development/ci_trigger_forward_variables.yml b/config/feature_flags/development/work_items_hierarchy.yml
index 4767ca0cb75..439fb941eb9 100644
--- a/config/feature_flags/development/ci_trigger_forward_variables.yml
+++ b/config/feature_flags/development/work_items_hierarchy.yml
@@ -1,8 +1,8 @@
---
-name: ci_trigger_forward_variables
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/82676
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/355572
-milestone: '14.9'
+name: work_items_hierarchy
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/88504
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/363447
+milestone: '15.1'
type: development
-group: group::pipeline authoring
-default_enabled: true
+group: group::product planning
+default_enabled: false
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
index 780ef1cf2ac..28f5eaf92d7 100644
--- a/config/sidekiq_queues.yml
+++ b/config/sidekiq_queues.yml
@@ -233,10 +233,6 @@
- 1
- - issuables_clear_groups_issue_counter
- 1
-- - issue_placement
- - 2
-- - issue_rebalancing
- - 1
- - issues_placement
- 2
- - issues_rebalancing
diff --git a/doc/administration/gitaly/monitoring.md b/doc/administration/gitaly/monitoring.md
index 7a4f2026f3d..66c57e4753d 100644
--- a/doc/administration/gitaly/monitoring.md
+++ b/doc/administration/gitaly/monitoring.md
@@ -144,6 +144,7 @@ The following metrics are available from the `/metrics` endpoint:
- `gitaly_praefect_node_latency_bucket`, a histogram measuring the latency in Gitaly returning
health check information to Praefect. This indicates Praefect connection saturation. Available in
GitLab 12.10 and later.
+- `gitaly_praefect_connections_total`, the total number of connections to Praefect. [Introduced](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/4220) in GitLab 14.7.
To monitor [strong consistency](index.md#strong-consistency), you can use the following Prometheus metrics:
diff --git a/doc/ci/yaml/index.md b/doc/ci/yaml/index.md
index 6766aa082b3..3b3ddb9af2e 100644
--- a/doc/ci/yaml/index.md
+++ b/doc/ci/yaml/index.md
@@ -3706,12 +3706,9 @@ successfully complete before starting.
#### `trigger:forward`
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213729) in GitLab 14.9 [with a flag](../../administration/feature_flags.md) named `ci_trigger_forward_variables`. Disabled by default.
-
-FLAG:
-On self-managed GitLab, by default this feature is not available. To make it available,
-ask an administrator to [enable the feature flag](../../administration/feature_flags.md) named `ci_trigger_forward_variables`.
-The feature is not ready for production use.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213729) in GitLab 14.9 [with a flag](../../administration/feature_flags.md) named `ci_trigger_forward_variables`. Disabled by default.
+> - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/355572) in GitLab 14.10.
+> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/355572) in GitLab 15.1. [Feature flag ci_trigger_forward_variables](https://gitlab.com/gitlab-org/gitlab/-/issues/355572) removed.
Use `trigger:forward` to specify what to forward to the downstream pipeline. You can control
what is forwarded to both [parent-child pipelines](../pipelines/parent_child_pipelines.md)
diff --git a/doc/development/testing_guide/best_practices.md b/doc/development/testing_guide/best_practices.md
index 7ae49d33e91..1c17d056a08 100644
--- a/doc/development/testing_guide/best_practices.md
+++ b/doc/development/testing_guide/best_practices.md
@@ -215,6 +215,39 @@ In this case, the `total time` and `top-level time` numbers match more closely:
8 8 0.0477s 0.0477s 0.0477s namespace
```
+#### Stubbing methods within factories
+
+You should avoid using `allow(object).to receive(:method)` in factories, as this makes the factory unable to be used with `let_it_be`.
+
+Instead, you can use `stub_method` to stub the method:
+
+```ruby
+ before(:create) do |user, evaluator|
+ # Stub a method.
+ stub_method(user, :some_method) { 'stubbed!' }
+ # Or with arguments, including named ones
+ stub_method(user, :some_method) { |var1| "Returning #{var1}!" }
+ stub_method(user, :some_method) { |var1: 'default'| "Returning #{var1}!" }
+ end
+
+ # Un-stub the method.
+ # This may be useful where the stubbed object is created with `let_it_be`
+ # and you want to reset the method between tests.
+ after(:create) do |user, evaluator|
+ restore_original_method(user, :some_method)
+ # or
+ restore_original_methods(user)
+ end
+```
+
+NOTE:
+`stub_method` does not work when used in conjunction with `let_it_be_with_refind`. This is because `stub_method` will stub a method on an instance and `let_it_be_with_refind` will create a new instance of the object for each run.
+
+`stub_method` does not support method existence and method arity checks.
+
+WARNING:
+`stub_method` is supposed to be used in factories only. It's strongly discouraged to be used elsewhere. Please consider using [RSpec's mocks](https://relishapp.com/rspec/rspec-mocks/v/3-10/docs/basics) if available.
+
#### Identify slow tests
Running a spec with profiling is a good way to start optimizing a spec. This can
diff --git a/doc/user/group/saml_sso/index.md b/doc/user/group/saml_sso/index.md
index a767dbb6d06..5a45272a9a0 100644
--- a/doc/user/group/saml_sso/index.md
+++ b/doc/user/group/saml_sso/index.md
@@ -182,10 +182,12 @@ Follow the Google Workspace documentation on
[setting up SSO with Google as your identity provider](https://support.google.com/a/answer/6087519?hl=en)
with the notes below for consideration.
-| GitLab setting | Google Workspace field |
-|:-------------------------------|:-----------------------|
-| Identifier | Entity ID |
-| Assertion consumer service URL | ACS URL |
+| GitLab setting | Google Workspace field |
+|:-------------------------------------|:-----------------------|
+| Identifier | Entity ID |
+| Assertion consumer service URL | ACS URL |
+| GitLab single sign-on URL | Start URL |
+| Identity provider single sign-on URL | SSO URL |
You must download the certificate to get the SHA1 certificate fingerprint.
@@ -200,8 +202,7 @@ For NameID, the following settings are recommended:
- **Name ID format** is set to `EMAIL`.
- **NameID** set to `Basic Information > Primary email`.
-When selecting **Verify SAML Configuration** on the GitLab SAML SSO page, disregard the warning about the NameID format
-"persistent" being recommended.
+When selecting **Verify SAML Configuration** on the GitLab SAML SSO page, disregard the warning recommending setting the NameID format to "persistent".
See the [troubleshooting page](../../../administration/troubleshooting/group_saml_scim.md#google-workspace) for an example configuration.
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 185df32c523..543ed89b726 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -42939,6 +42939,9 @@ msgstr ""
msgid "WorkItem|Child items"
msgstr ""
+msgid "WorkItem|Collapse child items"
+msgstr ""
+
msgid "WorkItem|Convert to work item"
msgstr ""
@@ -42948,6 +42951,9 @@ msgstr ""
msgid "WorkItem|Delete work item"
msgstr ""
+msgid "WorkItem|Expand child items"
+msgstr ""
+
msgid "WorkItem|New Task"
msgstr ""
diff --git a/qa/qa/specs/features/api/4_verify/api_variable_inheritance_with_forward_pipeline_variables_spec.rb b/qa/qa/specs/features/api/4_verify/api_variable_inheritance_with_forward_pipeline_variables_spec.rb
index d5bc31311cb..05484963391 100644
--- a/qa/qa/specs/features/api/4_verify/api_variable_inheritance_with_forward_pipeline_variables_spec.rb
+++ b/qa/qa/specs/features/api/4_verify/api_variable_inheritance_with_forward_pipeline_variables_spec.rb
@@ -1,13 +1,7 @@
# frozen_string_literal: true
module QA
- # TODO:
- # Remove FF :ci_trigger_forward_variables
- # when https://gitlab.com/gitlab-org/gitlab/-/issues/355572 is closed
- RSpec.describe 'Verify', :runner, feature_flag: {
- name: 'ci_trigger_forward_variables',
- scope: :global
- } do
+ RSpec.describe 'Verify', :runner do
describe 'Pipeline API defined variable inheritance' do
include_context 'variable inheritance test prep'
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb
index ae1d3e6d383..2280cc971a7 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb
@@ -36,7 +36,7 @@ module QA
mr_page.rebase!
- expect(mr_page).to have_merge_button
+ expect { mr_page.has_merge_button? }.to eventually_be_truthy.within(max_duration: 60, reload_page: mr_page)
mr_page.merge!
diff --git a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/ui_variable_inheritable_when_forward_pipeline_variables_true_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/ui_variable_inheritable_when_forward_pipeline_variables_true_spec.rb
index 07f45595e47..7782c0240e9 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/ui_variable_inheritable_when_forward_pipeline_variables_true_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/ui_variable_inheritable_when_forward_pipeline_variables_true_spec.rb
@@ -1,13 +1,7 @@
# frozen_string_literal: true
module QA
- # TODO:
- # Remove FF :ci_trigger_forward_variables
- # when https://gitlab.com/gitlab-org/gitlab/-/issues/355572 is closed
- RSpec.describe 'Verify', :runner, feature_flag: {
- name: 'ci_trigger_forward_variables',
- scope: :global
- } do
+ RSpec.describe 'Verify', :runner do
describe 'UI defined variable' do
include_context 'variable inheritance test prep'
diff --git a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/ui_variable_non_inheritable_when_forward_pipeline_variables_false_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/ui_variable_non_inheritable_when_forward_pipeline_variables_false_spec.rb
index efbcc2debf7..69a99483b38 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/ui_variable_non_inheritable_when_forward_pipeline_variables_false_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/ui_variable_non_inheritable_when_forward_pipeline_variables_false_spec.rb
@@ -1,13 +1,7 @@
# frozen_string_literal: true
module QA
- # TODO:
- # Remove FF :ci_trigger_forward_variables
- # when https://gitlab.com/gitlab-org/gitlab/-/issues/355572 is closed
- RSpec.describe 'Verify', :runner, feature_flag: {
- name: 'ci_trigger_forward_variables',
- scope: :global
- } do
+ RSpec.describe 'Verify', :runner do
describe 'UI defined variable' do
include_context 'variable inheritance test prep'
diff --git a/qa/qa/specs/features/shared_contexts/variable_inheritance_shared_context.rb b/qa/qa/specs/features/shared_contexts/variable_inheritance_shared_context.rb
index 0c4eee2909e..45caeced35c 100644
--- a/qa/qa/specs/features/shared_contexts/variable_inheritance_shared_context.rb
+++ b/qa/qa/specs/features/shared_contexts/variable_inheritance_shared_context.rb
@@ -45,13 +45,11 @@ module QA
end
before do
- Runtime::Feature.enable(:ci_trigger_forward_variables)
Flow::Login.sign_in
end
after do
runner.remove_via_api!
- Runtime::Feature.disable(:ci_trigger_forward_variables)
end
def start_pipeline_with_variable
diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb
index 56c12d73a3b..645c519aca2 100644
--- a/spec/factories/ci/builds.rb
+++ b/spec/factories/ci/builds.rb
@@ -494,13 +494,15 @@ FactoryBot.define do
trait :with_commit do
after(:build) do |build|
- allow(build).to receive(:commit).and_return build(:commit, :without_author)
+ commit = build(:commit, :without_author)
+ stub_method(build, :commit) { commit }
end
end
trait :with_commit_and_author do
after(:build) do |build|
- allow(build).to receive(:commit).and_return build(:commit)
+ commit = build(:commit)
+ stub_method(build, :commit) { commit }
end
end
diff --git a/spec/factories/clusters/applications/helm.rb b/spec/factories/clusters/applications/helm.rb
index 10fa739acc1..919b45e57e2 100644
--- a/spec/factories/clusters/applications/helm.rb
+++ b/spec/factories/clusters/applications/helm.rb
@@ -10,19 +10,18 @@ FactoryBot.define do
before(:create) do |_record, evaluator|
if evaluator.helm_installed
- allow(Gitlab::Kubernetes::Helm::V2::Certificate).to receive(:generate_root)
- .and_return(
- double(
- key_string: File.read(Rails.root.join('spec/fixtures/clusters/sample_key.key')),
- cert_string: File.read(Rails.root.join('spec/fixtures/clusters/sample_cert.pem'))
- )
+ stub_method(Gitlab::Kubernetes::Helm::V2::Certificate, :generate_root) do
+ OpenStruct.new( # rubocop: disable Style/OpenStructUse
+ key_string: File.read(Rails.root.join('spec/fixtures/clusters/sample_key.key')),
+ cert_string: File.read(Rails.root.join('spec/fixtures/clusters/sample_cert.pem'))
)
+ end
end
end
after(:create) do |_record, evaluator|
if evaluator.helm_installed
- allow(Gitlab::Kubernetes::Helm::V2::Certificate).to receive(:generate_root).and_call_original
+ restore_original_methods(Gitlab::Kubernetes::Helm::V2::Certificate)
end
end
diff --git a/spec/factories/commits.rb b/spec/factories/commits.rb
index d006f9baf1f..4b1c74110ef 100644
--- a/spec/factories/commits.rb
+++ b/spec/factories/commits.rb
@@ -28,19 +28,20 @@ FactoryBot.define do
end
after(:build) do |commit, evaluator|
- allow(commit).to receive(:author).and_return(evaluator.author || build_stubbed(:author))
- allow(commit).to receive(:parent_ids).and_return([])
+ author = evaluator.author || build_stubbed(:author)
+ stub_method(commit, :author) { author }
+ stub_method(commit, :parent_ids) { [] }
end
trait :merge_commit do
after(:build) do |commit|
- allow(commit).to receive(:parent_ids).and_return(Array.new(2) { SecureRandom.hex(20) })
+ stub_method(commit, :parent_ids) { Array.new(2) { SecureRandom.hex(20) } }
end
end
trait :without_author do
after(:build) do |commit|
- allow(commit).to receive(:author).and_return nil
+ stub_method(commit, :author) { nil }
end
end
end
diff --git a/spec/factories/container_repositories.rb b/spec/factories/container_repositories.rb
index ce83e9e8006..210441430b0 100644
--- a/spec/factories/container_repositories.rb
+++ b/spec/factories/container_repositories.rb
@@ -85,13 +85,12 @@ FactoryBot.define do
tags = evaluator.tags
# convert Array into Hash
tags = tags.product(['sha256:4c8e63ca4cb663ce6c688cb06f1c372b088dac5b6d7ad7d49cd620d85cf72a15']).to_h unless tags.is_a?(Hash)
-
- allow(repository.client)
- .to receive(:repository_tags)
- .and_return({
+ stub_method(repository.client, :repository_tags) do |*args|
+ {
'name' => repository.path,
'tags' => tags.keys
- })
+ }
+ end
tags.each_pair do |tag, digest|
allow(repository.client)
diff --git a/spec/factories/deployments.rb b/spec/factories/deployments.rb
index ab1b794632a..204b917fa4a 100644
--- a/spec/factories/deployments.rb
+++ b/spec/factories/deployments.rb
@@ -15,7 +15,7 @@ FactoryBot.define do
deployment.user ||= deployment.project.creator
unless deployment.project.repository_exists?
- allow(deployment.project.repository).to receive(:create_ref)
+ stub_method(deployment.project.repository, :create_ref) { nil }
end
if deployment.cluster && deployment.cluster.project_type? && deployment.cluster.project.nil?
diff --git a/spec/factories/merge_requests.rb b/spec/factories/merge_requests.rb
index cba66b5d414..4941a31982f 100644
--- a/spec/factories/merge_requests.rb
+++ b/spec/factories/merge_requests.rb
@@ -320,7 +320,7 @@ FactoryBot.define do
# Fake `fetch_ref!` if we don't have repository
# We have too many existing tests relying on this behaviour
unless [target_project, source_project].all?(&:repository_exists?)
- allow(merge_request).to receive(:fetch_ref!)
+ stub_method(merge_request, :fetch_ref!) { nil }
end
end
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index c3c02782578..a5efadefc76 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -301,8 +301,8 @@ FactoryBot.define do
trait :stubbed_repository do
after(:build) do |project|
- allow(project).to receive(:empty_repo?).and_return(false)
- allow(project.repository).to receive(:empty?).and_return(false)
+ stub_method(project, :empty_repo?) { false }
+ stub_method(project.repository, :empty?) { false }
end
end
diff --git a/spec/helpers/routing/pseudonymization_helper_spec.rb b/spec/helpers/routing/pseudonymization_helper_spec.rb
index cf716931fe2..dd4cc55ed2b 100644
--- a/spec/helpers/routing/pseudonymization_helper_spec.rb
+++ b/spec/helpers/routing/pseudonymization_helper_spec.rb
@@ -8,8 +8,7 @@ RSpec.describe ::Routing::PseudonymizationHelper do
let_it_be(:project) { create(:project, group: group) }
let_it_be(:subproject) { create(:project, group: subgroup) }
let_it_be(:issue) { create(:issue, project: project) }
-
- let(:merge_request) { create(:merge_request, source_project: project) }
+ let_it_be(:merge_request) { create(:merge_request, source_project: project) }
let(:subject) { helper.masked_page_url(group: group, project: project) }
diff --git a/spec/lib/gitlab/ci/status/build/play_spec.rb b/spec/lib/gitlab/ci/status/build/play_spec.rb
index bb406623d2f..ade07a54877 100644
--- a/spec/lib/gitlab/ci/status/build/play_spec.rb
+++ b/spec/lib/gitlab/ci/status/build/play_spec.rb
@@ -3,9 +3,10 @@
require 'spec_helper'
RSpec.describe Gitlab::Ci::Status::Build::Play do
- let(:user) { create(:user) }
- let(:project) { create(:project, :stubbed_repository) }
- let(:build) { create(:ci_build, :manual, project: project) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :stubbed_repository) }
+ let_it_be_with_refind(:build) { create(:ci_build, :manual, project: project) }
+
let(:status) { Gitlab::Ci::Status::Core.new(build, user) }
subject { described_class.new(status) }
diff --git a/spec/lib/gitlab/ci/status/build/scheduled_spec.rb b/spec/lib/gitlab/ci/status/build/scheduled_spec.rb
index b0cd1ac4dc5..a9f9b82767e 100644
--- a/spec/lib/gitlab/ci/status/build/scheduled_spec.rb
+++ b/spec/lib/gitlab/ci/status/build/scheduled_spec.rb
@@ -3,8 +3,9 @@
require 'spec_helper'
RSpec.describe Gitlab::Ci::Status::Build::Scheduled do
- let(:user) { create(:user) }
- let(:project) { create(:project, :stubbed_repository) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :stubbed_repository) }
+
let(:build) { create(:ci_build, :scheduled, project: project) }
let(:status) { Gitlab::Ci::Status::Core.new(build, user) }
diff --git a/spec/models/ci/bridge_spec.rb b/spec/models/ci/bridge_spec.rb
index 6409ea9fc3d..cb29cce554f 100644
--- a/spec/models/ci/bridge_spec.rb
+++ b/spec/models/ci/bridge_spec.rb
@@ -259,25 +259,16 @@ RSpec.describe Ci::Bridge do
context 'forward variables' do
using RSpec::Parameterized::TableSyntax
- where(:yaml_variables, :pipeline_variables, :ff, :variables) do
- nil | nil | true | %w[BRIDGE]
- nil | false | true | %w[BRIDGE]
- nil | true | true | %w[BRIDGE PVAR1]
- false | nil | true | %w[]
- false | false | true | %w[]
- false | true | true | %w[PVAR1]
- true | nil | true | %w[BRIDGE]
- true | false | true | %w[BRIDGE]
- true | true | true | %w[BRIDGE PVAR1]
- nil | nil | false | %w[BRIDGE]
- nil | false | false | %w[BRIDGE]
- nil | true | false | %w[BRIDGE]
- false | nil | false | %w[BRIDGE]
- false | false | false | %w[BRIDGE]
- false | true | false | %w[BRIDGE]
- true | nil | false | %w[BRIDGE]
- true | false | false | %w[BRIDGE]
- true | true | false | %w[BRIDGE]
+ where(:yaml_variables, :pipeline_variables, :variables) do
+ nil | nil | %w[BRIDGE]
+ nil | false | %w[BRIDGE]
+ nil | true | %w[BRIDGE PVAR1]
+ false | nil | %w[]
+ false | false | %w[]
+ false | true | %w[PVAR1]
+ true | nil | %w[BRIDGE]
+ true | false | %w[BRIDGE]
+ true | true | %w[BRIDGE PVAR1]
end
with_them do
@@ -292,10 +283,6 @@ RSpec.describe Ci::Bridge do
}
end
- before do
- stub_feature_flags(ci_trigger_forward_variables: ff)
- end
-
it 'returns variables according to the forward value' do
expect(bridge.downstream_variables.map { |v| v[:key] }).to contain_exactly(*variables)
end
diff --git a/spec/support/factory_bot.rb b/spec/support/factory_bot.rb
index 5f22fa11e9e..6faa2db3330 100644
--- a/spec/support/factory_bot.rb
+++ b/spec/support/factory_bot.rb
@@ -2,6 +2,7 @@
FactoryBot::SyntaxRunner.class_eval do
include RSpec::Mocks::ExampleMethods
+ include StubMethodCalls
# FactoryBot doesn't allow yet to add a helper that can be used in factories
# While the fixture_file_upload helper is reasonable to be used there:
diff --git a/spec/support/helpers/stub_method_calls.rb b/spec/support/helpers/stub_method_calls.rb
new file mode 100644
index 00000000000..45d704958ca
--- /dev/null
+++ b/spec/support/helpers/stub_method_calls.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+# Used to stud methods for factories where we can't
+# use rspec-mocks.
+#
+# Examples:
+# stub_method(user, :some_method) { |var1, var2| var1 + var2 }
+# stub_method(user, :some_method) { true }
+# stub_method(user, :some_method) => nil
+# stub_method(user, :some_method) do |*args|
+# true
+# end
+#
+# restore_original_method(user, :some_method)
+# restore_original_methods(user)
+#
+module StubMethodCalls
+ AlreadyImplementedError = Class.new(StandardError)
+
+ def stub_method(object, method, &block)
+ Backup.stub_method(object, method, &block)
+ end
+
+ def restore_original_method(object, method)
+ Backup.restore_method(object, method)
+ end
+
+ def restore_original_methods(object)
+ Backup.stubbed_methods(object).each_key { |method, backed_up_method| restore_original_method(object, method) }
+ end
+
+ module Backup
+ def self.stubbed_methods(object)
+ return {} unless object.respond_to?(:_stubbed_methods)
+
+ object._stubbed_methods
+ end
+
+ def self.backup_method(object, method)
+ backed_up_methods = stubbed_methods(object)
+ backed_up_methods[method] = object.respond_to?(method) ? object.method(method) : nil
+
+ object.define_singleton_method(:_stubbed_methods) { backed_up_methods }
+ end
+
+ def self.stub_method(object, method, &block)
+ raise ArgumentError, "Block is required" unless block_given?
+
+ backup_method(object, method) unless backed_up_method?(object, method)
+ object.define_singleton_method(method, &block)
+ end
+
+ def self.restore_method(object, method)
+ raise NotImplementedError, "#{method} has not been stubbed on #{object}" unless backed_up_method?(object, method)
+
+ object.singleton_class.remove_method(method)
+ backed_up_method = stubbed_methods(object)[method]
+
+ object.define_singleton_method(method, backed_up_method) if backed_up_method
+ end
+
+ def self.backed_up_method?(object, method)
+ stubbed_methods(object).key?(method)
+ end
+ end
+end
diff --git a/spec/support_specs/helpers/stub_method_calls_spec.rb b/spec/support_specs/helpers/stub_method_calls_spec.rb
new file mode 100644
index 00000000000..837a2162bcd
--- /dev/null
+++ b/spec/support_specs/helpers/stub_method_calls_spec.rb
@@ -0,0 +1,107 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe StubMethodCalls do
+ include described_class
+
+ let(:object) do
+ Class.new do
+ def self.test_method
+ 'test'
+ end
+
+ def self.test_method_two(response: nil)
+ response || 'test_two'
+ end
+ end
+ end
+
+ describe '#stub_method' do
+ let(:method_to_stub) { :test_method }
+
+ it 'stubs the method response' do
+ stub_method(object, method_to_stub) { true }
+
+ expect(object.send(method_to_stub)).to eq(true)
+ end
+
+ context 'when calling it on an already stubbed method' do
+ before do
+ stub_method(object, method_to_stub) { false }
+ end
+
+ it 'stubs correctly' do
+ stub_method(object, method_to_stub) { true }
+
+ expect(object.send(method_to_stub)).to eq(true)
+ end
+ end
+
+ context 'methods that accept arguments' do
+ it 'stubs correctly' do
+ stub_method(object, method_to_stub) { |a, b| a + b }
+
+ expect(object.send(method_to_stub, 1, 2)).to eq(3)
+ end
+
+ context 'methods that use named arguments' do
+ let(:method_to_stub) { :test_method_two }
+
+ it 'stubs correctly' do
+ stub_method(object, method_to_stub) { |a: 'test'| a }
+
+ expect(object.send(method_to_stub, a: 'testing')).to eq('testing')
+ expect(object.send(method_to_stub)).to eq('test')
+ end
+
+ context 'stubbing non-existent method' do
+ let(:method_to_stub) { :another_method }
+
+ it 'stubs correctly' do
+ stub_method(object, method_to_stub) { |a: 'test'| a }
+
+ expect(object.send(method_to_stub, a: 'testing')).to eq('testing')
+ expect(object.send(method_to_stub)).to eq('test')
+ end
+ end
+ end
+ end
+ end
+
+ describe '#restore_original_method' do
+ before do
+ stub_method(object, :test_method) { true }
+ end
+
+ it 'restores original behaviour' do
+ expect(object.test_method).to eq(true)
+
+ restore_original_method(object, :test_method)
+
+ expect(object.test_method).to eq('test')
+ end
+
+ context 'method is not stubbed' do
+ specify do
+ expect do
+ restore_original_method(object, 'some_other_method')
+ end.to raise_error(NotImplementedError, "some_other_method has not been stubbed on #{object}")
+ end
+ end
+ end
+
+ describe '#restore_original_methods' do
+ before do
+ stub_method(object, :test_method) { true }
+ stub_method(object, :test_method_two) { true }
+ end
+
+ it 'restores original behaviour' do
+ restore_original_methods(object)
+
+ expect(object.test_method).to eq('test')
+ expect(object.test_method_two).to eq('test_two')
+ end
+ end
+end
diff --git a/spec/workers/every_sidekiq_worker_spec.rb b/spec/workers/every_sidekiq_worker_spec.rb
index c15d1198ded..b1532b01d3f 100644
--- a/spec/workers/every_sidekiq_worker_spec.rb
+++ b/spec/workers/every_sidekiq_worker_spec.rb
@@ -308,8 +308,6 @@ RSpec.describe 'Every Sidekiq worker' do
'InvalidGpgSignatureUpdateWorker' => 3,
'IrkerWorker' => 3,
'IssuableExportCsvWorker' => 3,
- 'IssuePlacementWorker' => 3,
- 'IssueRebalancingWorker' => 3,
'Issues::PlacementWorker' => 3,
'Issues::RebalancingWorker' => 3,
'IterationsUpdateStatusWorker' => 3,
diff --git a/spec/workers/issue_placement_worker_spec.rb b/spec/workers/issue_placement_worker_spec.rb
deleted file mode 100644
index 9b5121d98e8..00000000000
--- a/spec/workers/issue_placement_worker_spec.rb
+++ /dev/null
@@ -1,151 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe IssuePlacementWorker do
- describe '#perform' do
- let_it_be(:time) { Time.now.utc }
- let_it_be(:group) { create(:group) }
- let_it_be(:project) { create(:project, group: group) }
- let_it_be(:author) { create(:user) }
- let_it_be(:common_attrs) { { author: author, project: project } }
- let_it_be(:unplaced) { common_attrs.merge(relative_position: nil) }
- let_it_be_with_reload(:issue) { create(:issue, **unplaced, created_at: time) }
- let_it_be_with_reload(:issue_a) { create(:issue, **unplaced, created_at: time - 1.minute) }
- let_it_be_with_reload(:issue_b) { create(:issue, **unplaced, created_at: time - 2.minutes) }
- let_it_be_with_reload(:issue_c) { create(:issue, **unplaced, created_at: time + 1.minute) }
- let_it_be_with_reload(:issue_d) { create(:issue, **unplaced, created_at: time + 2.minutes) }
- let_it_be_with_reload(:issue_e) { create(:issue, **common_attrs, relative_position: 10, created_at: time + 1.minute) }
- let_it_be_with_reload(:issue_f) { create(:issue, **unplaced, created_at: time + 1.minute) }
-
- let_it_be(:irrelevant) { create(:issue, relative_position: nil, created_at: time) }
-
- shared_examples 'running the issue placement worker' do
- let(:issue_id) { issue.id }
- let(:project_id) { project.id }
-
- it 'places all issues created at most 5 minutes before this one at the end, most recent last' do
- expect { run_worker }.not_to change { irrelevant.reset.relative_position }
-
- expect(project.issues.order_by_relative_position)
- .to eq([issue_e, issue_b, issue_a, issue, issue_c, issue_f, issue_d])
- expect(project.issues.where(relative_position: nil)).not_to exist
- end
-
- it 'schedules rebalancing if needed' do
- issue_a.update!(relative_position: RelativePositioning::MAX_POSITION)
-
- expect(Issues::RebalancingWorker).to receive(:perform_async).with(nil, nil, project.group.id)
-
- run_worker
- end
-
- context 'there are more than QUERY_LIMIT unplaced issues' do
- before_all do
- # Ensure there are more than N issues in this set
- n = described_class::QUERY_LIMIT
- create_list(:issue, n - 5, **unplaced)
- end
-
- it 'limits the sweep to QUERY_LIMIT records, and reschedules placement' do
- expect(Issue).to receive(:move_nulls_to_end)
- .with(have_attributes(count: described_class::QUERY_LIMIT))
- .and_call_original
-
- expect(Issues::PlacementWorker).to receive(:perform_async).with(nil, project.id)
-
- run_worker
-
- expect(project.issues.where(relative_position: nil)).to exist
- end
-
- it 'is eventually correct' do
- prefix = project.issues.where.not(relative_position: nil).order(:relative_position).to_a
- moved = project.issues.where.not(id: prefix.map(&:id))
-
- run_worker
-
- expect(project.issues.where(relative_position: nil)).to exist
-
- run_worker
-
- expect(project.issues.where(relative_position: nil)).not_to exist
- expect(project.issues.order(:relative_position)).to eq(prefix + moved.order(:created_at, :id))
- end
- end
-
- context 'we are passed bad IDs' do
- let(:issue_id) { non_existing_record_id }
- let(:project_id) { non_existing_record_id }
-
- def max_positions_by_project
- Issue
- .group(:project_id)
- .pluck(:project_id, Issue.arel_table[:relative_position].maximum.as('max_relative_position'))
- .to_h
- end
-
- it 'does move any issues to the end' do
- expect { run_worker }.not_to change { max_positions_by_project }
- end
-
- context 'the project_id refers to an empty project' do
- let!(:project_id) { create(:project).id }
-
- it 'does move any issues to the end' do
- expect { run_worker }.not_to change { max_positions_by_project }
- end
- end
- end
-
- it 'anticipates the failure to place the issues, and schedules rebalancing' do
- allow(Issue).to receive(:move_nulls_to_end) { raise RelativePositioning::NoSpaceLeft }
-
- expect(Issues::RebalancingWorker).to receive(:perform_async).with(nil, nil, project.group.id)
- expect(Gitlab::ErrorTracking)
- .to receive(:log_exception)
- .with(RelativePositioning::NoSpaceLeft, worker_arguments)
-
- run_worker
- end
- end
-
- context 'passing an issue ID' do
- def run_worker
- described_class.new.perform(issue_id)
- end
-
- let(:worker_arguments) { { issue_id: issue_id, project_id: nil } }
-
- it_behaves_like 'running the issue placement worker'
-
- context 'when block_issue_repositioning is enabled' do
- let(:issue_id) { issue.id }
- let(:project_id) { project.id }
-
- before do
- stub_feature_flags(block_issue_repositioning: group)
- end
-
- it 'does not run repositioning tasks' do
- expect { run_worker }.not_to change { issue.reset.relative_position }
- end
- end
- end
-
- context 'passing a project ID' do
- def run_worker
- described_class.new.perform(nil, project_id)
- end
-
- let(:worker_arguments) { { issue_id: nil, project_id: project_id } }
-
- it_behaves_like 'running the issue placement worker'
- end
- end
-
- it 'has the `until_executed` deduplicate strategy' do
- expect(described_class.get_deduplicate_strategy).to eq(:until_executed)
- expect(described_class.get_deduplication_options).to include({ including_scheduled: true })
- end
-end
diff --git a/spec/workers/issue_rebalancing_worker_spec.rb b/spec/workers/issue_rebalancing_worker_spec.rb
deleted file mode 100644
index cfb19af05b3..00000000000
--- a/spec/workers/issue_rebalancing_worker_spec.rb
+++ /dev/null
@@ -1,104 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe IssueRebalancingWorker, :clean_gitlab_redis_shared_state do
- describe '#perform' do
- let_it_be(:group) { create(:group) }
- let_it_be(:project) { create(:project, group: group) }
- let_it_be(:issue) { create(:issue, project: project) }
-
- shared_examples 'running the worker' do
- it 'runs an instance of Issues::RelativePositionRebalancingService' do
- service = double(execute: nil)
- service_param = arguments.second.present? ? kind_of(Project.id_in([project]).class) : kind_of(group&.all_projects.class)
-
- expect(Issues::RelativePositionRebalancingService).to receive(:new).with(service_param).and_return(service)
-
- described_class.new.perform(*arguments)
- end
-
- it 'anticipates there being too many concurent rebalances' do
- service = double
- service_param = arguments.second.present? ? kind_of(Project.id_in([project]).class) : kind_of(group&.all_projects.class)
-
- allow(service).to receive(:execute).and_raise(Issues::RelativePositionRebalancingService::TooManyConcurrentRebalances)
- expect(Issues::RelativePositionRebalancingService).to receive(:new).with(service_param).and_return(service)
- expect(Gitlab::ErrorTracking).to receive(:log_exception).with(Issues::RelativePositionRebalancingService::TooManyConcurrentRebalances, include(project_id: arguments.second, root_namespace_id: arguments.third))
-
- described_class.new.perform(*arguments)
- end
-
- it 'takes no action if the value is nil' do
- expect(Issues::RelativePositionRebalancingService).not_to receive(:new)
- expect(Gitlab::ErrorTracking).not_to receive(:log_exception)
-
- described_class.new.perform # all arguments are nil
- end
-
- it 'does not schedule a new rebalance if it finished under 1h ago' do
- container_type = arguments.second.present? ? ::Gitlab::Issues::Rebalancing::State::PROJECT : ::Gitlab::Issues::Rebalancing::State::NAMESPACE
- container_id = arguments.second || arguments.third
-
- Gitlab::Redis::SharedState.with do |redis|
- redis.set(::Gitlab::Issues::Rebalancing::State.send(:recently_finished_key, container_type, container_id), true)
- end
-
- expect(Issues::RelativePositionRebalancingService).not_to receive(:new)
- expect(Gitlab::ErrorTracking).not_to receive(:log_exception)
-
- described_class.new.perform(*arguments)
- end
- end
-
- shared_examples 'safely handles non-existent ids' do
- it 'anticipates the inability to find the issue' do
- expect(Gitlab::ErrorTracking).to receive(:log_exception).with(ArgumentError, include(project_id: arguments.second, root_namespace_id: arguments.third))
- expect(Issues::RelativePositionRebalancingService).not_to receive(:new)
-
- described_class.new.perform(*arguments)
- end
- end
-
- context 'without root_namespace param' do
- it_behaves_like 'running the worker' do
- let(:arguments) { [-1, project.id] }
- end
-
- it_behaves_like 'safely handles non-existent ids' do
- let(:arguments) { [nil, -1] }
- end
-
- include_examples 'an idempotent worker' do
- let(:job_args) { [-1, project.id] }
- end
-
- include_examples 'an idempotent worker' do
- let(:job_args) { [nil, -1] }
- end
- end
-
- context 'with root_namespace param' do
- it_behaves_like 'running the worker' do
- let(:arguments) { [nil, nil, group.id] }
- end
-
- it_behaves_like 'safely handles non-existent ids' do
- let(:arguments) { [nil, nil, -1] }
- end
-
- include_examples 'an idempotent worker' do
- let(:job_args) { [nil, nil, group.id] }
- end
-
- include_examples 'an idempotent worker' do
- let(:job_args) { [nil, nil, -1] }
- end
- end
- end
-
- it 'has the `until_executed` deduplicate strategy' do
- expect(described_class.get_deduplicate_strategy).to eq(:until_executed)
- expect(described_class.get_deduplication_options).to include({ including_scheduled: true })
- end
-end