diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml
index d05d0e32263..a28b42c11b5 100644
--- a/.gitlab/ci/rules.gitlab-ci.yml
+++ b/.gitlab/ci/rules.gitlab-ci.yml
@@ -2699,7 +2699,7 @@
when: never
- if: '$DEPENDENCY_SCANNING_DISABLED || $GITLAB_FEATURES !~ /\bdependency_scanning\b/ || $DS_EXCLUDED_ANALYZERS =~ /gemnasium([^-]|$)/'
when: never
- # Run Dependency Scanning on master until https://gitlab.com/gitlab-org/gitlab/-/issues/361657 is resolved
+ # Run Dependency Scanning on master until https://gitlab.com/gitlab-org/gitlab/-/issues/504908#note_2218591981 is resolved
- <<: *if-default-branch-refs
- <<: *if-default-refs
changes: *dependency-patterns
@@ -2710,7 +2710,7 @@
when: never
- if: '$DEPENDENCY_SCANNING_DISABLED || $GITLAB_FEATURES !~ /\bdependency_scanning\b/ || $DS_EXCLUDED_ANALYZERS =~ /gemnasium-python/'
when: never
- # Run Dependency Scanning on master until https://gitlab.com/gitlab-org/gitlab/-/issues/361657 is resolved
+ # Run Dependency Scanning on master until https://gitlab.com/gitlab-org/gitlab/-/issues/504908#note_2218591981 is resolved
- <<: *if-default-branch-refs
- <<: *if-default-refs
changes: *python-patterns
diff --git a/.rubocop_todo/gitlab/bounded_contexts.yml b/.rubocop_todo/gitlab/bounded_contexts.yml
index 76bef1fb0bf..c94ab5dc058 100644
--- a/.rubocop_todo/gitlab/bounded_contexts.yml
+++ b/.rubocop_todo/gitlab/bounded_contexts.yml
@@ -436,14 +436,6 @@ Gitlab/BoundedContexts:
- 'app/graphql/types/container_expiration_policy_keep_enum.rb'
- 'app/graphql/types/container_expiration_policy_older_than_enum.rb'
- 'app/graphql/types/container_expiration_policy_type.rb'
- - 'app/graphql/types/container_repository_cleanup_status_enum.rb'
- - 'app/graphql/types/container_repository_details_type.rb'
- - 'app/graphql/types/container_repository_referrer_type.rb'
- - 'app/graphql/types/container_repository_sort_enum.rb'
- - 'app/graphql/types/container_repository_status_enum.rb'
- - 'app/graphql/types/container_repository_tag_type.rb'
- - 'app/graphql/types/container_repository_tags_sort_enum.rb'
- - 'app/graphql/types/container_repository_type.rb'
- 'app/graphql/types/countable_connection_type.rb'
- 'app/graphql/types/current_user_todos.rb'
- 'app/graphql/types/current_user_type.rb'
diff --git a/.rubocop_todo/graphql/descriptions.yml b/.rubocop_todo/graphql/descriptions.yml
index 27e91a5cbe9..5ab98be73dd 100644
--- a/.rubocop_todo/graphql/descriptions.yml
+++ b/.rubocop_todo/graphql/descriptions.yml
@@ -2,7 +2,6 @@
# Cop supports --autocorrect.
Graphql/Descriptions:
Exclude:
- - 'app/graphql/types/container_repository_type.rb'
- 'app/graphql/types/deployment_tag_type.rb'
- 'app/graphql/types/design_management/design_at_version_type.rb'
- 'app/graphql/types/design_management/design_fields.rb'
diff --git a/.rubocop_todo/graphql/extract_type.yml b/.rubocop_todo/graphql/extract_type.yml
index 6392e21d12f..d2cb473d20f 100644
--- a/.rubocop_todo/graphql/extract_type.yml
+++ b/.rubocop_todo/graphql/extract_type.yml
@@ -27,7 +27,6 @@ GraphQL/ExtractType:
- 'app/graphql/types/commit_type.rb'
- 'app/graphql/types/container_expiration_policy_type.rb'
- 'app/graphql/types/container_registry/protection/rule_type.rb'
- - 'app/graphql/types/container_repository_type.rb'
- 'app/graphql/types/diff_type.rb'
- 'app/graphql/types/environment_type.rb'
- 'app/graphql/types/error_tracking/sentry_detailed_error_type.rb'
diff --git a/.rubocop_todo/graphql/resource_not_available_error.yml b/.rubocop_todo/graphql/resource_not_available_error.yml
index 4ba40ed488b..3c1e4fee7b3 100644
--- a/.rubocop_todo/graphql/resource_not_available_error.yml
+++ b/.rubocop_todo/graphql/resource_not_available_error.yml
@@ -21,8 +21,6 @@ Graphql/ResourceNotAvailableError:
- 'app/graphql/resolvers/kas/agent_configurations_resolver.rb'
- 'app/graphql/resolvers/kas/agent_connections_resolver.rb'
- 'app/graphql/resolvers/projects/snippets_resolver.rb'
- - 'app/graphql/types/container_repository_details_type.rb'
- - 'app/graphql/types/container_repository_type.rb'
- 'ee/app/graphql/mutations/ai/action.rb'
- 'ee/app/graphql/mutations/audit_events/instance_external_audit_event_destinations/base.rb'
- 'ee/app/graphql/mutations/issues/set_escalation_policy.rb'
diff --git a/.rubocop_todo/layout/array_alignment.yml b/.rubocop_todo/layout/array_alignment.yml
index 84fdb629088..5fa3151f5d4 100644
--- a/.rubocop_todo/layout/array_alignment.yml
+++ b/.rubocop_todo/layout/array_alignment.yml
@@ -123,7 +123,6 @@ Layout/ArrayAlignment:
- 'spec/graphql/resolvers/project_issues_resolver_spec.rb'
- 'spec/graphql/types/blob_viewer_type_spec.rb'
- 'spec/graphql/types/boards/board_issue_input_type_spec.rb'
- - 'spec/graphql/types/container_repository_details_type_spec.rb'
- 'spec/graphql/types/container_repository_type_spec.rb'
- 'spec/graphql/types/issuable_sort_enum_spec.rb'
- 'spec/graphql/types/issue_type_spec.rb'
diff --git a/.rubocop_todo/layout/line_length.yml b/.rubocop_todo/layout/line_length.yml
index 5e68043b74f..20535304c01 100644
--- a/.rubocop_todo/layout/line_length.yml
+++ b/.rubocop_todo/layout/line_length.yml
@@ -63,9 +63,6 @@ Layout/LineLength:
- 'app/graphql/types/ci/runner_type.rb'
- 'app/graphql/types/ci/runner_web_url_edge.rb'
- 'app/graphql/types/container_expiration_policy_type.rb'
- - 'app/graphql/types/container_repository_cleanup_status_enum.rb'
- - 'app/graphql/types/container_repository_details_type.rb'
- - 'app/graphql/types/container_repository_type.rb'
- 'app/graphql/types/dependency_proxy/group_setting_type.rb'
- 'app/graphql/types/dependency_proxy/image_ttl_group_policy_type.rb'
- 'app/graphql/types/environment_type.rb'
diff --git a/.rubocop_todo/rspec/contain_exactly.yml b/.rubocop_todo/rspec/contain_exactly.yml
index 0ddfa6eb31f..df37f8b848f 100644
--- a/.rubocop_todo/rspec/contain_exactly.yml
+++ b/.rubocop_todo/rspec/contain_exactly.yml
@@ -105,8 +105,6 @@ RSpec/ContainExactly:
- 'spec/graphql/types/ci/pipeline_schedule_sort_enum_spec.rb'
- 'spec/graphql/types/ci/pipeline_scope_enum_spec.rb'
- 'spec/graphql/types/ci/pipeline_status_enum_spec.rb'
- - 'spec/graphql/types/container_repository_cleanup_status_enum_spec.rb'
- - 'spec/graphql/types/container_repository_status_enum_spec.rb'
- 'spec/graphql/types/issuable_searchable_field_enum_spec.rb'
- 'spec/graphql/types/issuable_severity_enum_spec.rb'
- 'spec/graphql/types/merge_requests/mergeability_check_identifier_enum_spec.rb'
diff --git a/.rubocop_todo/rspec/feature_category.yml b/.rubocop_todo/rspec/feature_category.yml
index f73dbcdd27b..dbbeefdc047 100644
--- a/.rubocop_todo/rspec/feature_category.yml
+++ b/.rubocop_todo/rspec/feature_category.yml
@@ -1616,10 +1616,6 @@ RSpec/FeatureCategory:
- 'spec/graphql/types/container_expiration_policy_keep_enum_spec.rb'
- 'spec/graphql/types/container_expiration_policy_older_than_enum_spec.rb'
- 'spec/graphql/types/container_expiration_policy_type_spec.rb'
- - 'spec/graphql/types/container_repository_cleanup_status_enum_spec.rb'
- - 'spec/graphql/types/container_repository_sort_enum_spec.rb'
- - 'spec/graphql/types/container_repository_status_enum_spec.rb'
- - 'spec/graphql/types/container_respository_tags_sort_enum_spec.rb'
- 'spec/graphql/types/countable_connection_type_spec.rb'
- 'spec/graphql/types/current_user_todos_type_spec.rb'
- 'spec/graphql/types/custom_emoji_type_spec.rb'
diff --git a/.rubocop_todo/style/hash_each_methods.yml b/.rubocop_todo/style/hash_each_methods.yml
index 175c26c2132..b451d36452a 100644
--- a/.rubocop_todo/style/hash_each_methods.yml
+++ b/.rubocop_todo/style/hash_each_methods.yml
@@ -12,7 +12,6 @@ Style/HashEachMethods:
- 'app/graphql/types/ci/runner_access_level_enum.rb'
- 'app/graphql/types/ci/variable_type_enum.rb'
- 'app/graphql/types/clusters/agent_token_status_enum.rb'
- - 'app/graphql/types/container_repository_status_enum.rb'
- 'app/graphql/types/data_visualization_palette/color_enum.rb'
- 'app/graphql/types/data_visualization_palette/weight_enum.rb'
- 'app/graphql/types/dependency_proxy/manifest_type_enum.rb'
diff --git a/Gemfile.checksum b/Gemfile.checksum
index c63ca060d6c..cbce40905fe 100644
--- a/Gemfile.checksum
+++ b/Gemfile.checksum
@@ -84,7 +84,7 @@
{"name":"coderay","version":"1.1.3","platform":"ruby","checksum":"dc530018a4684512f8f38143cd2a096c9f02a1fc2459edcfe534787a7fc77d4b"},
{"name":"coercible","version":"1.0.0","platform":"ruby","checksum":"5081ad24352cc8435ce5472bc2faa30260c7ea7f2102cc6a9f167c4d9bffaadc"},
{"name":"colored2","version":"3.1.2","platform":"ruby","checksum":"b13c2bd7eeae2cf7356a62501d398e72fde78780bd26aec6a979578293c28b4a"},
-{"name":"commonmarker","version":"0.23.10","platform":"ruby","checksum":"fdd312ae2bb4071b2f3085d4d7533cb9f8d9057a2eaa0760228a65bc3ed565d1"},
+{"name":"commonmarker","version":"0.23.11","platform":"ruby","checksum":"9d1d35d358740151bce29235aebfecc63314fb57dd89a83e72d4061b4fe3d2bf"},
{"name":"concurrent-ruby","version":"1.2.3","platform":"ruby","checksum":"82fdd3f8a0816e28d513e637bb2b90a45d7b982bdf4f3a0511722d2e495801e2"},
{"name":"connection_pool","version":"2.4.1","platform":"ruby","checksum":"0f40cf997091f1f04ff66da67eabd61a9fe0d4928b9a3645228532512fab62f4"},
{"name":"console","version":"1.25.2","platform":"ruby","checksum":"460fbf8c1b0e527b2c275448b76f91c3e9fb72e6bead5d27fb5a638fc191e943"},
diff --git a/Gemfile.lock b/Gemfile.lock
index afdeec07f48..71305f2e361 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -437,7 +437,7 @@ GEM
coercible (1.0.0)
descendants_tracker (~> 0.0.1)
colored2 (3.1.2)
- commonmarker (0.23.10)
+ commonmarker (0.23.11)
concurrent-ruby (1.2.3)
connection_pool (2.4.1)
console (1.25.2)
diff --git a/Gemfile.next.checksum b/Gemfile.next.checksum
index affab4a454d..8d92ebda438 100644
--- a/Gemfile.next.checksum
+++ b/Gemfile.next.checksum
@@ -84,7 +84,7 @@
{"name":"coderay","version":"1.1.3","platform":"ruby","checksum":"dc530018a4684512f8f38143cd2a096c9f02a1fc2459edcfe534787a7fc77d4b"},
{"name":"coercible","version":"1.0.0","platform":"ruby","checksum":"5081ad24352cc8435ce5472bc2faa30260c7ea7f2102cc6a9f167c4d9bffaadc"},
{"name":"colored2","version":"3.1.2","platform":"ruby","checksum":"b13c2bd7eeae2cf7356a62501d398e72fde78780bd26aec6a979578293c28b4a"},
-{"name":"commonmarker","version":"0.23.10","platform":"ruby","checksum":"fdd312ae2bb4071b2f3085d4d7533cb9f8d9057a2eaa0760228a65bc3ed565d1"},
+{"name":"commonmarker","version":"0.23.11","platform":"ruby","checksum":"9d1d35d358740151bce29235aebfecc63314fb57dd89a83e72d4061b4fe3d2bf"},
{"name":"concurrent-ruby","version":"1.2.3","platform":"ruby","checksum":"82fdd3f8a0816e28d513e637bb2b90a45d7b982bdf4f3a0511722d2e495801e2"},
{"name":"connection_pool","version":"2.4.1","platform":"ruby","checksum":"0f40cf997091f1f04ff66da67eabd61a9fe0d4928b9a3645228532512fab62f4"},
{"name":"console","version":"1.25.2","platform":"ruby","checksum":"460fbf8c1b0e527b2c275448b76f91c3e9fb72e6bead5d27fb5a638fc191e943"},
@@ -410,7 +410,7 @@
{"name":"murmurhash3","version":"0.1.7","platform":"ruby","checksum":"370a2ce2e9ab0711e51554e530b5f63956927a6554a296855f42a1a4a5ed0936"},
{"name":"mustermann","version":"3.0.0","platform":"ruby","checksum":"6d3569aa3c3b2f048c60626f48d9b2d561cc8d2ef269296943b03da181c08b67"},
{"name":"mustermann-grape","version":"1.0.2","platform":"ruby","checksum":"6f5309d6a338f801f211c644e8c2d3cc2577a8693f9cd51dadfdb29c1260f5fe"},
-{"name":"mutex_m","version":"0.2.0","platform":"ruby","checksum":"b6ef0c6c842ede846f2ec0ade9e266b1a9dac0bc151682b04835e8ebd54840d5"},
+{"name":"mutex_m","version":"0.3.0","platform":"ruby","checksum":"cfcb04ac16b69c4813777022fdceda24e9f798e48092a2b817eb4c0a782b0751"},
{"name":"nap","version":"1.1.0","platform":"ruby","checksum":"949691660f9d041d75be611bb2a8d2fd559c467537deac241f4097d9b5eea576"},
{"name":"neighbor","version":"0.3.2","platform":"ruby","checksum":"b795bbcc24b1b9ae82d9f7e97a3461b0b3607d24a85a7acbed776bd498e7eba8"},
{"name":"nenv","version":"0.3.0","platform":"ruby","checksum":"d9de6d8fb7072228463bf61843159419c969edb34b3cef51832b516ae7972765"},
diff --git a/Gemfile.next.lock b/Gemfile.next.lock
index 56e96bd0b54..011a55c51f0 100644
--- a/Gemfile.next.lock
+++ b/Gemfile.next.lock
@@ -446,7 +446,7 @@ GEM
coercible (1.0.0)
descendants_tracker (~> 0.0.1)
colored2 (3.1.2)
- commonmarker (0.23.10)
+ commonmarker (0.23.11)
concurrent-ruby (1.2.3)
connection_pool (2.4.1)
console (1.25.2)
@@ -1177,7 +1177,7 @@ GEM
ruby2_keywords (~> 0.0.1)
mustermann-grape (1.0.2)
mustermann (>= 1.0.0)
- mutex_m (0.2.0)
+ mutex_m (0.3.0)
nap (1.1.0)
neighbor (0.3.2)
activerecord (>= 6.1)
diff --git a/app/assets/javascripts/todos/components/todo_item.vue b/app/assets/javascripts/todos/components/todo_item.vue
index 6a561ca1ac3..bc474ea7750 100644
--- a/app/assets/javascripts/todos/components/todo_item.vue
+++ b/app/assets/javascripts/todos/components/todo_item.vue
@@ -1,6 +1,6 @@
@@ -262,7 +273,13 @@ export default {
-
+
merge_request.id })
- end
+ )
end
def discussions_ready_to_merge?
diff --git a/app/services/merge_requests/post_merge_service.rb b/app/services/merge_requests/post_merge_service.rb
index f63bd704e80..19398c4c4ec 100644
--- a/app/services/merge_requests/post_merge_service.rb
+++ b/app/services/merge_requests/post_merge_service.rb
@@ -114,7 +114,6 @@ module MergeRequests
end
def cancel_auto_merges_targeting_source_branch(merge_request)
- return unless Feature.enabled?(:merge_when_checks_pass, merge_request.project)
return unless params[:delete_source_branch]
merge_request.source_project
diff --git a/app/services/merge_requests/update_service.rb b/app/services/merge_requests/update_service.rb
index b94bc68b7d7..4c0f4a54341 100644
--- a/app/services/merge_requests/update_service.rb
+++ b/app/services/merge_requests/update_service.rb
@@ -238,7 +238,7 @@ module MergeRequests
# email template itself, see `change_in_merge_request_draft_status_email` template.
notify_draft_status_changed(merge_request)
trigger_merge_request_status_updated(merge_request)
- publish_draft_change_event(merge_request) if Feature.enabled?(:merge_when_checks_pass, project)
+ publish_draft_change_event(merge_request)
end
if !old_title_draft && new_title_draft
diff --git a/app/views/projects/settings/access_tokens/index.html.haml b/app/views/projects/settings/access_tokens/index.html.haml
index d5e3c8ac2a4..5d6eb19fae6 100644
--- a/app/views/projects/settings/access_tokens/index.html.haml
+++ b/app/views/projects/settings/access_tokens/index.html.haml
@@ -4,12 +4,8 @@
- type_plural = _('project access tokens')
- @force_desktop_expanded_sidebar = true
-.settings-section.js-search-settings-section
- .settings-sticky-header
- .settings-sticky-header-inner
- %h4.gl-my-0
- = page_title
- %p.gl-text-secondary
+= render ::Layouts::SettingsSectionComponent.new(page_title) do |c|
+ - c.with_description do
- help_link_start = ''.html_safe % { url: help_page_path('user/project/settings/project_access_tokens.md') }
- if current_user.can?(:create_resource_access_tokens, @project)
= _('Generate project access tokens scoped to this project for your applications that need access to the GitLab API.')
@@ -21,32 +17,32 @@
- link = link_to('', edit_group_path(root_group), target: '_blank', rel: 'noopener noreferrer')
= safe_format(_('You can enable project access token creation in %{link_start}group settings%{link_end}.'), tag_pair(link, :link_start, :link_end))
= html_escape(_('You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}')) % { link_start: help_link_start, link_end: ''.html_safe }
+ - c.with_body do
+ #js-new-access-token-app{ data: { access_token_type: type } }
- #js-new-access-token-app{ data: { access_token_type: type } }
+ = render ::Layouts::CrudComponent.new(_('Active project access tokens'),
+ icon: 'token',
+ count: @active_access_tokens_size,
+ count_options: { class: 'js-token-count' },
+ form_options: { class: 'gl-hidden js-toggle-content js-add-new-token-form' },
+ options: { class: 'gl-mt-5 js-toggle-container js-token-card' }) do |c|
+ - c.with_actions do
+ - if current_user.can?(:create_resource_access_tokens, @project)
+ = render Pajamas::ButtonComponent.new(size: :small, button_options: { class: 'js-toggle-button js-toggle-content', data: { testid: 'add-new-token-button' } }) do
+ = _('Add new token')
- = render ::Layouts::CrudComponent.new(_('Active project access tokens'),
- icon: 'token',
- count: @active_access_tokens_size,
- count_options: { class: 'js-token-count' },
- form_options: { class: 'gl-hidden js-toggle-content js-add-new-token-form' },
- options: { class: 'gl-mt-5 js-toggle-container js-token-card' }) do |c|
- - c.with_actions do
- - if current_user.can?(:create_resource_access_tokens, @project)
- = render Pajamas::ButtonComponent.new(size: :small, button_options: { class: 'js-toggle-button js-toggle-content', data: { testid: 'add-new-token-button' } }) do
- = _('Add new token')
+ - c.with_form do
+ - if current_user.can?(:create_resource_access_tokens, @project)
+ = render_if_exists 'projects/settings/access_tokens/form', type: type
- - c.with_form do
- - if current_user.can?(:create_resource_access_tokens, @project)
- = render_if_exists 'projects/settings/access_tokens/form', type: type
+ - c.with_body do
+ #js-access-token-table-app{ data: { access_token_type: type, access_token_type_plural: type_plural, backend_pagination: 'true', initial_active_access_tokens: @active_access_tokens.to_json, no_active_tokens_message: _('This project has no active access tokens.'), show_role: true } }
- - c.with_body do
- #js-access-token-table-app{ data: { access_token_type: type, access_token_type_plural: type_plural, backend_pagination: 'true', initial_active_access_tokens: @active_access_tokens.to_json, no_active_tokens_message: _('This project has no active access tokens.'), show_role: true } }
-
- - if Feature.enabled?(:retain_resource_access_token_user_after_revoke, @project.root_ancestor)
- .gl-mt-5
- = render ::Layouts::CrudComponent.new(_('Inactive project access tokens'),
- icon: 'token',
- count: @inactive_access_tokens.size,
- count_options: { class: 'js-token-count' }) do |c|
- - c.with_body do
- #js-inactive-access-token-table-app{ data: { access_token_type: type, access_token_type_plural: type_plural, initial_inactive_access_tokens: @inactive_access_tokens.to_json, no_inactive_tokens_message: _('This project has no inactive access tokens.')} }
+ - if Feature.enabled?(:retain_resource_access_token_user_after_revoke, @project.root_ancestor)
+ .gl-mt-5
+ = render ::Layouts::CrudComponent.new(_('Inactive project access tokens'),
+ icon: 'token',
+ count: @inactive_access_tokens.size,
+ count_options: { class: 'js-token-count' }) do |c|
+ - c.with_body do
+ #js-inactive-access-token-table-app{ data: { access_token_type: type, access_token_type_plural: type_plural, initial_inactive_access_tokens: @inactive_access_tokens.to_json, no_inactive_tokens_message: _('This project has no inactive access tokens.')} }
diff --git a/app/workers/merge_requests/process_auto_merge_from_event_worker.rb b/app/workers/merge_requests/process_auto_merge_from_event_worker.rb
index 6d6f651fe75..5589dff7d0a 100644
--- a/app/workers/merge_requests/process_auto_merge_from_event_worker.rb
+++ b/app/workers/merge_requests/process_auto_merge_from_event_worker.rb
@@ -19,8 +19,6 @@ module MergeRequests
return
end
- return unless Feature.enabled?(:merge_when_checks_pass, merge_request.project)
-
AutoMergeService.new(merge_request.project, merge_request.merge_user)
.process(merge_request)
end
diff --git a/config/feature_flags/beta/merge_when_checks_pass.yml b/config/feature_flags/beta/merge_when_checks_pass.yml
deleted file mode 100644
index 9df51f55a66..00000000000
--- a/config/feature_flags/beta/merge_when_checks_pass.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: merge_when_checks_pass
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121828
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/412995
-milestone: '16.2'
-type: beta
-group: group::code review
-default_enabled: true
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 69fbd45ac53..004652f747c 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -21141,9 +21141,9 @@ A container repository.
| `name` | [`String!`](#string) | Name of the container repository. |
| `path` | [`String!`](#string) | Path of the container repository. |
| `project` | [`Project!`](#project) | Project of the container registry. |
-| `protectionRuleExists` **{warning-solid}** | [`Boolean!`](#boolean) | **Introduced** in GitLab 17.2. **Status**: Experiment. Whether any matching container protection rule exists for this container. Available only when feature flag `container_registry_protected_containers` is enabled. |
+| `protectionRuleExists` **{warning-solid}** | [`Boolean!`](#boolean) | **Introduced** in GitLab 17.2. **Status**: Experiment. Whether any matching container protection rule exists for the container. Available only when feature flag `container_registry_protected_containers` is enabled. |
| `status` | [`ContainerRepositoryStatus`](#containerrepositorystatus) | Status of the container repository. |
-| `tagsCount` | [`Int!`](#int) | Number of tags associated with this image. |
+| `tagsCount` | [`Int!`](#int) | Number of tags associated with the image. |
| `updatedAt` | [`Time!`](#time) | Timestamp when the container repository was updated. |
| `userPermissions` | [`ContainerRepositoryPermissions!`](#containerrepositorypermissions) | Permissions for the current user on the resource. |
@@ -21166,10 +21166,10 @@ Details of a container repository.
| `name` | [`String!`](#string) | Name of the container repository. |
| `path` | [`String!`](#string) | Path of the container repository. |
| `project` | [`Project!`](#project) | Project of the container registry. |
-| `protectionRuleExists` **{warning-solid}** | [`Boolean!`](#boolean) | **Introduced** in GitLab 17.2. **Status**: Experiment. Whether any matching container protection rule exists for this container. Available only when feature flag `container_registry_protected_containers` is enabled. |
+| `protectionRuleExists` **{warning-solid}** | [`Boolean!`](#boolean) | **Introduced** in GitLab 17.2. **Status**: Experiment. Whether any matching container protection rule exists for the container. Available only when feature flag `container_registry_protected_containers` is enabled. |
| `size` | [`Float`](#float) | Deduplicated size of the image repository in bytes. This is only available on GitLab.com for repositories created after `2021-11-04`. |
| `status` | [`ContainerRepositoryStatus`](#containerrepositorystatus) | Status of the container repository. |
-| `tagsCount` | [`Int!`](#int) | Number of tags associated with this image. |
+| `tagsCount` | [`Int!`](#int) | Number of tags associated with the image. |
| `updatedAt` | [`Time!`](#time) | Timestamp when the container repository was updated. |
| `userPermissions` | [`ContainerRepositoryPermissions!`](#containerrepositorypermissions) | Permissions for the current user on the resource. |
diff --git a/doc/development/api_graphql_styleguide.md b/doc/development/api_graphql_styleguide.md
index cf6194c0e72..7b2a5b5eb75 100644
--- a/doc/development/api_graphql_styleguide.md
+++ b/doc/development/api_graphql_styleguide.md
@@ -540,7 +540,7 @@ For example:
```ruby
field :tags,
- Types::ContainerRepositoryTagType.connection_type,
+ Types::ContainerRegistry::ContainerRepositoryTagType.connection_type,
null: true,
description: 'Tags of the container repository',
max_page_size: 20
@@ -2201,19 +2201,21 @@ Also see the [description style guide for sort enums](#sort-enums).
Example from [`ContainerRepositoriesResolver`](https://gitlab.com/gitlab-org/gitlab/-/blob/dad474605a06c8ed5404978b0a9bd187e9fded80/app/graphql/resolvers/container_repositories_resolver.rb#L13-16):
```ruby
-# Types::ContainerRepositorySortEnum:
+# Types::ContainerRegistry::ContainerRepositorySortEnum:
module Types
- class ContainerRepositorySortEnum < SortEnum
- graphql_name 'ContainerRepositorySort'
- description 'Values for sorting container repositories'
+ module ContainerRegistry
+ class ContainerRepositorySortEnum < SortEnum
+ graphql_name 'ContainerRepositorySort'
+ description 'Values for sorting container repositories'
- value 'NAME_ASC', 'Name by ascending order.', value: :name_asc
- value 'NAME_DESC', 'Name by descending order.', value: :name_desc
+ value 'NAME_ASC', 'Name by ascending order.', value: :name_asc
+ value 'NAME_DESC', 'Name by descending order.', value: :name_desc
+ end
end
end
# Resolvers::ContainerRepositoriesResolver:
-argument :sort, Types::ContainerRepositorySortEnum,
+argument :sort, Types::ContainerRegistry::ContainerRepositorySortEnum,
description: 'Sort container repositories by this criteria.',
required: false,
default_value: :created_desc
diff --git a/doc/development/fe_guide/emojis.md b/doc/development/fe_guide/emojis.md
index 39a788e02d1..b9956e0ce93 100644
--- a/doc/development/fe_guide/emojis.md
+++ b/doc/development/fe_guide/emojis.md
@@ -8,17 +8,27 @@ info: Any user with at least the Maintainer role can merge updates to this conte
GitLab supports native Emojis through the [`tanuki_emoji`](https://gitlab.com/gitlab-org/ruby/gems/tanuki_emoji) gem.
-NOTE:
-[`tanuki_emoji`](https://gitlab.com/gitlab-org/ruby/gems/tanuki_emoji) gem has replaced [`gemojione`](https://github.com/bonusly/gemojione). See [more information here](https://gitlab.com/gitlab-org/gitlab/-/issues/429653#note_1931385720).
-
## How to update Emojis
-1. Update the [`tanuki_emoji`](https://gitlab.com/gitlab-org/ruby/gems/tanuki_emoji) gem.
+Because our emoji support is implemented on both the backend and the frontend, we need to update support over three milestones.
+
+### First milestone (backend)
+
+1. Update the [`tanuki_emoji`](https://gitlab.com/gitlab-org/ruby/gems/tanuki_emoji) gem as needed.
+1. Update the `Gemfile` to use the latest `tanuki_emoji` gem.
+1. Update the `Gemfile` to use the latest [`unicode-emoji`](https://github.com/janlelis/unicode-emoji) that supports the version of Unicode you're upgrading to.
1. Update `EMOJI_VERSION` in `lib/gitlab/emoji.rb`
+1. `bundle exec rake tanuki_emoji:import` - imports all fallback images into the versioned `public/-/emojis` directory.
+ Ensure you see new individual images copied into there.
+1. When testing, you should be able to use the shortcodes of any new emojis and have them display.
+1. See example MRs [one](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/171446) and
+ [two](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/170289) for the backend.
+
+### Second milestone (frontend)
+
1. Update `EMOJI_VERSION` in `app/assets/javascripts/emoji/index.js`
-1. Use the [`tanuki_emoji`](https://gitlab.com/gitlab-org/ruby/gems/tanuki_emoji) gem's [Rake tasks](../rake_tasks.md) to update aliases, fallback images, digests, and sprites. Run in the following order:
+1. Use the [`tanuki_emoji`](https://gitlab.com/gitlab-org/ruby/gems/tanuki_emoji) gem's [Rake tasks](../rake_tasks.md) to update aliases, digests, and sprites. Run in the following order:
1. `bundle exec rake tanuki_emoji:aliases` - updates `fixtures/emojis/aliases.json`
- 1. `bundle exec rake tanuki_emoji:import` - imports all the images into `public/-/emojis` directory
1. `bundle exec rake tanuki_emoji:digests` - updates `public/-/emojis/VERSION/emojis.json` and `fixtures/emojis/digests.json`
1. `bundle exec rake tanuki_emoji:sprite` - creates new sprite sheets
@@ -36,17 +46,20 @@ NOTE:
- Positive intent should be set to `0.5`.
- Neutral intent can be set to `1`. This is applied to all emoji automatically so there is no need to set this explicitly.
- Negative intent should be set to `1.5`.
-1. Ensure you see new individual images copied into `app/assets/images/emoji/`
-1. Ensure you can see the new emojis and their aliases in the GitLab Flavored Markdown (GLFM) Autocomplete
-1. Ensure you can see the new emojis and their aliases in the emoji reactions menu
1. You might need to add new emoji Unicode support checks and rules for platforms
that do not support a certain emoji and we need to fallback to an image.
See `app/assets/javascripts/emoji/support/is_emoji_unicode_supported.js`
and `app/assets/javascripts/emoji/support/unicode_support_map.js`
- - if a new version of Unicode emojis is being added, update the list in `app/assets/javascripts/emoji/support/unicode_support_map.js`
1. Ensure you use the version of [emoji-regex](https://github.com/mathiasbynens/emoji-regex) that corresponds
to the version of Unicode that is being supported. This should be updated in `package.json`. Used for
filtering emojis in `app/assets/javascripts/emoji/index.js`.
1. Have there been any changes to the category names? If so then `app/assets/javascripts/emoji/constants.js`
will need to be updated
-1. See an [example MR](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/166790)
+1. When testing
+ 1. Ensure you can see the new emojis and their aliases in the GitLab Flavored Markdown (GLFM) Autocomplete
+ 1. Ensure you can see the new emojis and their aliases in the emoji reactions menu
+
+### Third milestone (cleanup)
+
+Remove any old emoji versions from the `public/-/emojis` directory. This is not strictly necessary -
+everything continues to work if you don't do this. However it's good to clean it up.
diff --git a/doc/user/application_security/api_security_testing/index.md b/doc/user/application_security/api_security_testing/index.md
index 9852152776a..13aa17e959b 100644
--- a/doc/user/application_security/api_security_testing/index.md
+++ b/doc/user/application_security/api_security_testing/index.md
@@ -51,6 +51,7 @@ other scanners) during a scan could cause inaccurate results.
The following projects demonstrate API security testing scanning:
+- [Example OpenAPI v3 Specification project](https://gitlab.com/gitlab-org/security-products/demos/api-dast/openapi-v3-example)
- [Example OpenAPI v2 Specification project](https://gitlab.com/gitlab-org/security-products/demos/api-dast/openapi-example)
- [Example HTTP Archive (HAR) project](https://gitlab.com/gitlab-org/security-products/demos/api-dast/har-example)
- [Example Postman Collection project](https://gitlab.com/gitlab-org/security-products/demos/api-dast/postman-example)
diff --git a/doc/user/application_security/policies/pipeline_execution_policies.md b/doc/user/application_security/policies/pipeline_execution_policies.md
index 70715805f65..336a933a751 100644
--- a/doc/user/application_security/policies/pipeline_execution_policies.md
+++ b/doc/user/application_security/policies/pipeline_execution_policies.md
@@ -118,6 +118,26 @@ When enforcing pipeline execution policies over projects whose CI/CD configurati
control, you should define jobs in the `.pipeline-policy-pre` and `.pipeline-policy-post` stages.
These stages are always available, regardless of any project's CI/CD configuration.
+When you use the `override_project_ci` [pipeline strategy](#pipeline-strategies) with multiple
+pipeline execution policies and with custom stages, the stages must be defined in the same relative order
+to be compatible with each other:
+
+Valid configuration example:
+
+```yaml
+ - `override-policy-1` stages: `[build, test, policy-test, deploy]`
+ - `override-policy-2` stages: `[test, deploy]`
+```
+
+Invalid configuration example:
+
+```yaml
+ - `override-policy-1` stages: `[build, test, policy-test, deploy]`
+ - `override-policy-2` stages: `[deploy, test]`
+```
+
+The pipeline fails if one or more `override_project_ci` policies has an invalid `stages` configuration.
+
### `content` type
| Field | Type | Required | Description |
@@ -199,12 +219,13 @@ compliance_job:
...
```
-NOTE:
-Jobs from the project configuration that are defined for a custom
-`stage` are excluded from the final pipeline.
-To include a job in the final configuration, define it for a
-[default pipeline stage](../../../ci/yaml/index.md#stages) or a reserved
-stage (`.pipeline-policy-pre` or `.pipeline-policy-post`).
+> Jobs from the project configuration that are defined for a custom
+> `stage` are excluded from the final pipeline.
+> To include a job in the final configuration, you can:
+>
+> - Use [stages](../../../ci/yaml/index.md#stages) to define custom stages in the pipeline execution policy configuration.
+> - Use a [default pipeline stage](../../../ci/yaml/index.md#stages)
+> - Use a reserved stage (`.pipeline-policy-pre` or `.pipeline-policy-post`).
## CI/CD variables
diff --git a/doc/user/project/merge_requests/auto_merge.md b/doc/user/project/merge_requests/auto_merge.md
index 07e419e9f3d..202969b7372 100644
--- a/doc/user/project/merge_requests/auto_merge.md
+++ b/doc/user/project/merge_requests/auto_merge.md
@@ -17,8 +17,9 @@ DETAILS:
> - [Enabled](https://gitlab.com/gitlab-org/gitlab/-/issues/412995) the flags `merge_when_checks_pass` and `additional_merge_when_checks_ready` on GitLab.com in GitLab 17.0.
> - [Merged](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/154366) the flag `additional_merge_when_checks_ready` with `merge_when_checks_pass` in GitLab 17.1.
> - [Enabled](https://gitlab.com/gitlab-org/gitlab/-/issues/412995) the flags `merge_when_checks_pass` by default in GitLab 17.4.
+> - Merge when checks pass [generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/412995) in GitLab 17.7. Feature flag `merge_when_checks_pass` removed.
-When you enable the `merge_when_checks_pass` feature flag, if the content of a merge request is ready to merge,
+If the content of a merge request is ready to merge,
you can select **Set to auto-merge**. The merge request auto-merges when all required checks complete successfully, and you don't need to remember to manually merge the merge request.
After you set auto-merge, these checks must all pass before the merge request merges:
diff --git a/lib/gitlab/database/partitioning/time/daily_strategy.rb b/lib/gitlab/database/partitioning/time/daily_strategy.rb
new file mode 100644
index 00000000000..f0d8e532e08
--- /dev/null
+++ b/lib/gitlab/database/partitioning/time/daily_strategy.rb
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module Partitioning
+ module Time
+ class DailyStrategy < BaseStrategy
+ HEADROOM = 28.days
+ PARTITION_SUFFIX = '%Y%m%d'
+
+ def current_partitions
+ Gitlab::Database::PostgresPartition.for_parent_table(table_name).map do |partition|
+ TimePartition.from_sql(table_name, partition.name, partition.condition)
+ end
+ end
+
+ # Check the currently existing partitions and determine which ones are missing
+ def missing_partitions
+ desired_partitions - current_partitions
+ end
+
+ def extra_partitions
+ partitions = current_partitions - desired_partitions
+ partitions.reject!(&:holds_data?) if retain_non_empty_partitions
+
+ partitions
+ end
+
+ def desired_partitions
+ [].tap do |parts|
+ min_date, max_date = relevant_range
+
+ if pruning_old_partitions? && min_date <= oldest_active_date
+ min_date = oldest_active_date.beginning_of_day.to_date
+ else
+ parts << partition_for(upper_bound: min_date)
+ end
+
+ while min_date < max_date
+ next_date = min_date.next_day
+
+ parts << partition_for(lower_bound: min_date, upper_bound: next_date)
+
+ min_date = next_date
+ end
+ end
+ end
+
+ def relevant_range
+ first_partition = current_partitions.min
+
+ if first_partition
+ # Case 1: First partition starts with MINVALUE, i.e. from is nil -> start with first real partition
+ # Case 2: Rather unexpectedly, first partition does not start with MINVALUE, i.e. from is not nil
+ # In this case, use first partition beginning as a start
+ min_date = first_partition.from || first_partition.to
+ end
+
+ min_date ||= oldest_active_date if pruning_old_partitions?
+
+ # In case we don't have a partition yet
+ min_date ||= Date.current
+ min_date = min_date.beginning_of_day.to_date
+
+ max_date = Date.current.end_of_day.to_date + HEADROOM
+
+ [min_date, max_date]
+ end
+
+ def oldest_active_date
+ retain_for.ago.beginning_of_day.to_date
+ end
+
+ def partition_name(lower_bound)
+ suffix = lower_bound&.strftime(PARTITION_SUFFIX) || '00000000'
+
+ "#{table_name}_#{suffix}"
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index c796bf5f4bd..dad87b877d9 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -57754,12 +57754,6 @@ msgid_plural "Todos|Marked %d to-dos as done"
msgstr[0] ""
msgstr[1] ""
-msgid "Todos|Marked as done"
-msgstr ""
-
-msgid "Todos|Marked as undone"
-msgstr ""
-
msgid "Todos|Member access request"
msgstr ""
diff --git a/scripts/frontend/quarantined_vue3_specs.txt b/scripts/frontend/quarantined_vue3_specs.txt
index 867b3eff7aa..eb94a3104f3 100644
--- a/scripts/frontend/quarantined_vue3_specs.txt
+++ b/scripts/frontend/quarantined_vue3_specs.txt
@@ -397,7 +397,6 @@ spec/frontend/vue_shared/components/page_heading_spec.js
spec/frontend/vue_shared/components/project_selector/project_selector_spec.js
spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js
spec/frontend/vue_shared/components/smart_virtual_list_spec.js
-spec/frontend/vue_shared/components/source_viewer/components/chunk_spec.js
spec/frontend/vue_shared/components/tooltip_on_truncate_spec.js
spec/frontend/vue_shared/components/upload_dropzone/upload_dropzone_spec.js
spec/frontend/vue_shared/directives/tooltip_on_truncate_spec.js
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index 53ca36ed642..3a24dda6daa 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -662,18 +662,6 @@ RSpec.describe Projects::MergeRequestsController, feature_category: :code_review
let(:status) { 'merge_when_checks_pass' }
let(:not_current_pipeline_status) { 'merge_when_checks_pass' }
end
-
- context 'when merge_when_checks_pass is false' do
- before do
- stub_feature_flags(merge_when_checks_pass: false)
- end
-
- it_behaves_like 'api merge with auto merge' do
- let(:service_class) { AutoMerge::MergeWhenPipelineSucceedsService }
- let(:status) { 'merge_when_pipeline_succeeds' }
- let(:not_current_pipeline_status) { 'failed' }
- end
- end
end
describe 'only_allow_merge_if_all_discussions_are_resolved? setting' do
diff --git a/spec/factories/merge_requests.rb b/spec/factories/merge_requests.rb
index 62ec00f4953..3da3b4070f3 100644
--- a/spec/factories/merge_requests.rb
+++ b/spec/factories/merge_requests.rb
@@ -137,7 +137,9 @@ FactoryBot.define do
auto_merge_enabled { true }
auto_merge_strategy { AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS }
merge_user { author }
- merge_params { { sha: diff_head_sha } }
+ merge_params do
+ { 'auto_merge_strategy' => AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS, sha: diff_head_sha }
+ end
end
trait :merge_when_checks_pass do
diff --git a/spec/features/merge_request/user_resolves_wip_mr_spec.rb b/spec/features/merge_request/user_resolves_wip_mr_spec.rb
index ac61e699375..e79796ad717 100644
--- a/spec/features/merge_request/user_resolves_wip_mr_spec.rb
+++ b/spec/features/merge_request/user_resolves_wip_mr_spec.rb
@@ -30,11 +30,7 @@ RSpec.describe 'Merge request > User resolves Draft', :js, feature_category: :co
end
context 'when there is active pipeline for merge request' do
- let(:feature_flags_state) { true }
-
before do
- stub_feature_flags(merge_when_checks_pass: feature_flags_state)
-
create(:ci_build, pipeline: pipeline)
sign_in(user)
@@ -58,27 +54,5 @@ RSpec.describe 'Merge request > User resolves Draft', :js, feature_category: :co
expect(page.find('.ci-widget-content', wait: 0)).to have_content("Pipeline ##{pipeline.id}")
expect(page).to have_content("Set to auto-merge")
end
-
- context 'when the new merge_when_checks_pass and merge blocked components are disabled' do
- let(:feature_flags_state) { false }
-
- it 'retains merge request data after clicking Resolve WIP status' do
- expect(page.find('.ci-widget-content')).to have_content("Pipeline ##{pipeline.id}")
- expect(page).to have_content "Merge blocked: 1 check failed"
- expect(page).to have_content "Merge request must not be draft"
-
- page.within('.mr-state-widget') do
- click_button('Mark as ready')
- end
-
- wait_for_requests
-
- # If we don't disable the wait here, the test will wait until the
- # merge request widget refreshes, which masks missing elements
- # that should already be present.
- expect(page.find('.ci-widget-content', wait: 0)).to have_content("Pipeline ##{pipeline.id}")
- expect(page).not_to have_content("Merge blocked")
- end
- end
end
end
diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb
index e4c937686f6..66f6f43e54e 100644
--- a/spec/features/merge_request/user_sees_merge_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb
@@ -331,34 +331,19 @@ RSpec.describe 'Merge request > User sees merge widget', :js, feature_category:
visit project_merge_request_path(project_only_mwps, merge_request_in_only_mwps_project)
end
- context 'when using merge when pipeline succeeds' do
- before do
- stub_feature_flags(merge_when_checks_pass: false)
- end
+ it 'is not allowed to set auto merge' do
+ # Wait for the `ci_status` and `merge_check` requests
+ wait_for_requests
- it 'is not allowed to merge' do
- # Wait for the `ci_status` and `merge_check` requests
- wait_for_requests
-
- expect(page).not_to have_selector('.accept-merge-request')
- end
- end
-
- context 'when using merge when checks pass' do
- it 'is not allowed to set auto merge' do
- # Wait for the `ci_status` and `merge_check` requests
- wait_for_requests
-
- expect(page).to have_selector('.accept-merge-request')
- end
+ expect(page).to have_selector('.accept-merge-request')
end
end
- context 'view merge request with MWPS enabled but automatically merge fails' do
+ context 'view merge request with auto merge enabled but automatically merge fails' do
before do
merge_request.update!(
auto_merge_enabled: true,
- auto_merge_strategy: AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS,
+ auto_merge_strategy: AutoMergeService::STRATEGY_MERGE_WHEN_CHECKS_PASS,
merge_user: merge_request.author,
merge_error: 'Something went wrong'
)
@@ -376,7 +361,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js, feature_category:
end
end
- context 'view merge request with MWPS enabled but automatically merge fails' do
+ context 'view merge request with auto merge enabled but automatically merge fails' do
before do
merge_request.update!(
merge_when_pipeline_succeeds: true,
diff --git a/spec/frontend/todos/components/todo_item_actions_spec.js b/spec/frontend/todos/components/todo_item_actions_spec.js
index a832fc30dc0..3414e8d17cb 100644
--- a/spec/frontend/todos/components/todo_item_actions_spec.js
+++ b/spec/frontend/todos/components/todo_item_actions_spec.js
@@ -16,9 +16,6 @@ describe('TodoItemActions', () => {
todo: mockTodo,
...props,
},
- provide: {
- currentTab: 0,
- },
});
};
@@ -43,13 +40,6 @@ describe('TodoItemActions', () => {
});
describe('tooltipTitle', () => {
- it('returns null when isLoading is true', () => {
- createComponent();
- // eslint-disable-next-line no-restricted-syntax
- wrapper.setData({ isLoading: true });
- expect(wrapper.vm.tooltipTitle).toBeNull();
- });
-
it('returns "Mark as done" for pending todo', () => {
createComponent();
expect(wrapper.vm.tooltipTitle).toBe('Mark as done');
diff --git a/spec/frontend/todos/components/todo_item_spec.js b/spec/frontend/todos/components/todo_item_spec.js
index 2835f4eda6f..9a339a95468 100644
--- a/spec/frontend/todos/components/todo_item_spec.js
+++ b/spec/frontend/todos/components/todo_item_spec.js
@@ -21,6 +21,9 @@ describe('TodoItem', () => {
},
...props,
},
+ provide: {
+ currentTab: 0,
+ },
});
};
@@ -49,16 +52,23 @@ describe('TodoItem', () => {
expect(wrapper.findComponent(TodoItemActions).exists()).toBe(true);
});
+ describe('state based style', () => {
+ it('applies background when todo is done', () => {
+ createComponent({ todo: { state: TODO_STATE_DONE } });
+ expect(wrapper.attributes('class')).toContain('gl-bg-subtle');
+ });
+
+ it('applies no background when todo is pending', () => {
+ createComponent({ todo: { state: TODO_STATE_PENDING } });
+ expect(wrapper.attributes('class')).not.toContain('gl-bg-subtle');
+ });
+ });
+
describe('computed properties', () => {
it('isDone returns true when todo state is done', () => {
createComponent({ todo: { state: TODO_STATE_DONE } });
expect(wrapper.vm.isDone).toBe(true);
});
-
- it('isPending returns true when todo state is pending', () => {
- createComponent({ todo: { state: TODO_STATE_PENDING } });
- expect(wrapper.vm.isPending).toBe(true);
- });
});
it('emits change event when TodoItemActions emits change', async () => {
diff --git a/spec/frontend/todos/components/todos_app_spec.js b/spec/frontend/todos/components/todos_app_spec.js
index 48a42f51711..ef310feefa8 100644
--- a/spec/frontend/todos/components/todos_app_spec.js
+++ b/spec/frontend/todos/components/todos_app_spec.js
@@ -41,6 +41,7 @@ describe('TodosApp', () => {
const findMarkAllDoneButton = () => wrapper.findComponent(TodosMarkAllDoneButton);
const findRefreshButton = () => wrapper.findByTestId('refresh-todos');
const findPendingTodosCount = () => wrapper.findByTestId('pending-todos-count');
+ const findTodoItemListContainer = () => wrapper.findByTestId('todo-item-list-container');
it('should have a tracking event for each tab', () => {
expect(STATUS_BY_TAB.length).toBe(INSTRUMENT_TAB_LABELS.length);
@@ -145,6 +146,61 @@ describe('TodosApp', () => {
expect(todosCountsQuerySuccessHandler).toHaveBeenCalledTimes(2);
});
+ it('refetches todos one second after the cursor leaves the list of todos', async () => {
+ jest.useFakeTimers();
+ createComponent();
+
+ // Wait and account for initial query
+ await waitForPromises();
+ expect(todosQuerySuccessHandler).toHaveBeenCalledTimes(1);
+ expect(todosCountsQuerySuccessHandler).toHaveBeenCalledTimes(1);
+
+ // Simulate interacting with a todo item then mousing out of the list zone
+ wrapper.vm.handleItemChanged(1, true);
+ const list = findTodoItemListContainer();
+ list.trigger('mouseleave');
+
+ // Should refresh the count, but not the list
+ await waitForPromises();
+ expect(todosQuerySuccessHandler).toHaveBeenCalledTimes(1);
+ expect(todosCountsQuerySuccessHandler).toHaveBeenCalledTimes(2);
+
+ // Run out the clock
+ jest.advanceTimersByTime(1000 + 50); // 1s + some jitter
+
+ // Refreshes the count and the list
+ await waitForPromises();
+ expect(todosQuerySuccessHandler).toHaveBeenCalledTimes(2);
+ expect(todosCountsQuerySuccessHandler).toHaveBeenCalledTimes(3);
+ });
+
+ it('does not refresh todos after the cursor leaves the list of todos if nothing changed', async () => {
+ jest.useFakeTimers();
+ createComponent();
+
+ // Wait and account for initial query
+ await waitForPromises();
+ expect(todosQuerySuccessHandler).toHaveBeenCalledTimes(1);
+ expect(todosCountsQuerySuccessHandler).toHaveBeenCalledTimes(1);
+
+ // Simulate NOT interacting with a todo item then mousing out of the list zone
+ const list = findTodoItemListContainer();
+ list.trigger('mouseleave');
+
+ // Should not update anything
+ await waitForPromises();
+ expect(todosQuerySuccessHandler).toHaveBeenCalledTimes(1);
+ expect(todosCountsQuerySuccessHandler).toHaveBeenCalledTimes(1);
+
+ // Run out the clock
+ jest.advanceTimersByTime(1000 + 50); // 1s + some jitter
+
+ // Should not update anything
+ await waitForPromises();
+ expect(todosQuerySuccessHandler).toHaveBeenCalledTimes(1);
+ expect(todosCountsQuerySuccessHandler).toHaveBeenCalledTimes(1);
+ });
+
it('passes the default status to the filter bar', () => {
createComponent();
diff --git a/spec/graphql/mutations/merge_requests/accept_spec.rb b/spec/graphql/mutations/merge_requests/accept_spec.rb
index d0820fbb412..529c8fe651e 100644
--- a/spec/graphql/mutations/merge_requests/accept_spec.rb
+++ b/spec/graphql/mutations/merge_requests/accept_spec.rb
@@ -94,23 +94,6 @@ RSpec.describe Mutations::MergeRequests::Accept, feature_category: :api do
end
expect(result).to include(errors: be_empty, merge_request: be_auto_merge_enabled)
end
-
- context 'when merge_when_checks_pass is off' do
- before do
- stub_feature_flags(merge_when_checks_pass: false)
- end
-
- let(:merge_request) { create(:merge_request, :with_head_pipeline, source_project: project) }
- let(:strategy) { ::Types::MergeStrategyEnum.values['MERGE_WHEN_PIPELINE_SUCCEEDS'].value }
- let(:additional_args) { { auto_merge_strategy: strategy } }
-
- it "can use the MERGE_WHEN_PIPELINE_SUCCEEDS strategy" do
- expect_next_found_instance_of(MergeRequest) do |instance|
- expect(instance).not_to receive(:merge_async)
- end
- expect(result).to include(errors: be_empty, merge_request: be_auto_merge_enabled)
- end
- end
end
end
end
diff --git a/spec/graphql/types/container_repository_cleanup_status_enum_spec.rb b/spec/graphql/types/container_registry/container_repository_cleanup_status_enum_spec.rb
similarity index 77%
rename from spec/graphql/types/container_repository_cleanup_status_enum_spec.rb
rename to spec/graphql/types/container_registry/container_repository_cleanup_status_enum_spec.rb
index 36cfc789ee9..1ccce7d52b2 100644
--- a/spec/graphql/types/container_repository_cleanup_status_enum_spec.rb
+++ b/spec/graphql/types/container_registry/container_repository_cleanup_status_enum_spec.rb
@@ -2,12 +2,12 @@
require 'spec_helper'
-RSpec.describe GitlabSchema.types['ContainerRepositoryCleanupStatus'] do
+RSpec.describe GitlabSchema.types['ContainerRepositoryCleanupStatus'], feature_category: :container_registry do
it 'exposes all statuses' do
expected_keys = ContainerRepository.expiration_policy_cleanup_statuses
.keys
.map { |k| k.gsub('cleanup_', '') }
.map(&:upcase)
- expect(described_class.values.keys).to contain_exactly(*expected_keys)
+ expect(described_class.values.keys).to match_array(expected_keys)
end
end
diff --git a/spec/graphql/types/container_repository_details_type_spec.rb b/spec/graphql/types/container_registry/container_repository_details_type_spec.rb
similarity index 69%
rename from spec/graphql/types/container_repository_details_type_spec.rb
rename to spec/graphql/types/container_registry/container_repository_details_type_spec.rb
index ed4fc1a8daa..18c4c947c9d 100644
--- a/spec/graphql/types/container_repository_details_type_spec.rb
+++ b/spec/graphql/types/container_registry/container_repository_details_type_spec.rb
@@ -4,9 +4,9 @@ require 'spec_helper'
RSpec.describe GitlabSchema.types['ContainerRepositoryDetails'], feature_category: :container_registry do
fields = %i[id name path location created_at updated_at expiration_policy_started_at
- status tags_count expiration_policy_cleanup_status tags size manifest
- project migration_state last_cleanup_deleted_tags_count user_permissions last_published_at
- protection_rule_exists]
+ status tags_count expiration_policy_cleanup_status tags size manifest
+ project migration_state last_cleanup_deleted_tags_count user_permissions last_published_at
+ protection_rule_exists]
it { expect(described_class.graphql_name).to eq('ContainerRepositoryDetails') }
@@ -20,7 +20,7 @@ RSpec.describe GitlabSchema.types['ContainerRepositoryDetails'], feature_categor
subject { described_class.fields['tags'] }
it 'returns tags connection type' do
- is_expected.to have_graphql_type(Types::ContainerRepositoryTagType.connection_type)
+ is_expected.to have_graphql_type(Types::ContainerRegistry::ContainerRepositoryTagType.connection_type)
end
end
end
diff --git a/spec/graphql/types/container_repository_referrer_type_spec.rb b/spec/graphql/types/container_registry/container_repository_referrer_type_spec.rb
similarity index 100%
rename from spec/graphql/types/container_repository_referrer_type_spec.rb
rename to spec/graphql/types/container_registry/container_repository_referrer_type_spec.rb
diff --git a/spec/graphql/types/container_repository_sort_enum_spec.rb b/spec/graphql/types/container_registry/container_repository_sort_enum_spec.rb
similarity index 76%
rename from spec/graphql/types/container_repository_sort_enum_spec.rb
rename to spec/graphql/types/container_registry/container_repository_sort_enum_spec.rb
index eb936c6d3a1..8507ab79b24 100644
--- a/spec/graphql/types/container_repository_sort_enum_spec.rb
+++ b/spec/graphql/types/container_registry/container_repository_sort_enum_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe GitlabSchema.types['ContainerRepositorySort'] do
+RSpec.describe GitlabSchema.types['ContainerRepositorySort'], feature_category: :container_registry do
specify { expect(described_class.graphql_name).to eq('ContainerRepositorySort') }
it_behaves_like 'common sort values'
diff --git a/spec/graphql/types/container_registry/container_repository_status_enum_spec.rb b/spec/graphql/types/container_registry/container_repository_status_enum_spec.rb
new file mode 100644
index 00000000000..a0b5dce6d8a
--- /dev/null
+++ b/spec/graphql/types/container_registry/container_repository_status_enum_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['ContainerRepositoryStatus'], feature_category: :container_registry do
+ it 'exposes all statuses' do
+ expect(described_class.values.keys).to match_array(ContainerRepository.statuses.keys.map(&:upcase))
+ end
+end
diff --git a/spec/graphql/types/container_repository_tag_type_spec.rb b/spec/graphql/types/container_registry/container_repository_tag_type_spec.rb
similarity index 100%
rename from spec/graphql/types/container_repository_tag_type_spec.rb
rename to spec/graphql/types/container_registry/container_repository_tag_type_spec.rb
diff --git a/spec/graphql/types/container_repository_type_spec.rb b/spec/graphql/types/container_registry/container_repository_type_spec.rb
similarity index 77%
rename from spec/graphql/types/container_repository_type_spec.rb
rename to spec/graphql/types/container_registry/container_repository_type_spec.rb
index a968d3cd9cc..3a97a37662d 100644
--- a/spec/graphql/types/container_repository_type_spec.rb
+++ b/spec/graphql/types/container_registry/container_repository_type_spec.rb
@@ -6,8 +6,8 @@ RSpec.describe GitlabSchema.types['ContainerRepository'], feature_category: :con
include GraphqlHelpers
fields = %i[id name path location created_at updated_at expiration_policy_started_at
- status tags_count expiration_policy_cleanup_status project
- migration_state last_cleanup_deleted_tags_count user_permissions protection_rule_exists]
+ status tags_count expiration_policy_cleanup_status project
+ migration_state last_cleanup_deleted_tags_count user_permissions protection_rule_exists]
it { expect(described_class.graphql_name).to eq('ContainerRepository') }
@@ -23,7 +23,7 @@ RSpec.describe GitlabSchema.types['ContainerRepository'], feature_category: :con
subject { described_class.fields['status'] }
it 'returns status enum' do
- is_expected.to have_graphql_type(Types::ContainerRepositoryStatusEnum)
+ is_expected.to have_graphql_type(Types::ContainerRegistry::ContainerRepositoryStatusEnum)
end
end
@@ -31,7 +31,7 @@ RSpec.describe GitlabSchema.types['ContainerRepository'], feature_category: :con
subject { described_class.fields['expirationPolicyCleanupStatus'] }
it 'returns cleanup status enum' do
- is_expected.to have_graphql_type(Types::ContainerRepositoryCleanupStatusEnum)
+ is_expected.to have_graphql_type(Types::ContainerRegistry::ContainerRepositoryCleanupStatusEnum)
end
end
diff --git a/spec/graphql/types/container_respository_tags_sort_enum_spec.rb b/spec/graphql/types/container_registry/container_respository_tags_sort_enum_spec.rb
similarity index 75%
rename from spec/graphql/types/container_respository_tags_sort_enum_spec.rb
rename to spec/graphql/types/container_registry/container_respository_tags_sort_enum_spec.rb
index cfc44f6e992..2aaf9105b76 100644
--- a/spec/graphql/types/container_respository_tags_sort_enum_spec.rb
+++ b/spec/graphql/types/container_registry/container_respository_tags_sort_enum_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe GitlabSchema.types['ContainerRepositoryTagSort'] do
+RSpec.describe GitlabSchema.types['ContainerRepositoryTagSort'], feature_category: :container_registry do
specify { expect(described_class.graphql_name).to eq('ContainerRepositoryTagSort') }
it 'exposes all the existing issue sort values' do
diff --git a/spec/graphql/types/container_repository_status_enum_spec.rb b/spec/graphql/types/container_repository_status_enum_spec.rb
deleted file mode 100644
index 9598879779a..00000000000
--- a/spec/graphql/types/container_repository_status_enum_spec.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe GitlabSchema.types['ContainerRepositoryStatus'] do
- it 'exposes all statuses' do
- expect(described_class.values.keys).to contain_exactly(*ContainerRepository.statuses.keys.map(&:upcase))
- end
-end
diff --git a/spec/graphql/types/merge_request_type_spec.rb b/spec/graphql/types/merge_request_type_spec.rb
index 6624f3b14b5..d3e664271c1 100644
--- a/spec/graphql/types/merge_request_type_spec.rb
+++ b/spec/graphql/types/merge_request_type_spec.rb
@@ -164,8 +164,8 @@ RSpec.describe GitlabSchema.types['MergeRequest'], feature_category: :code_revie
end
end
- context 'when MR is set to merge when pipeline succeeds' do
- let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds, target_project: project, source_project: project) }
+ context 'when MR is set to auto merge' do
+ let(:merge_request) { create(:merge_request, :merge_when_checks_pass, target_project: project, source_project: project) }
it 'is not nil' do
value = resolve_field(:merge_user, merge_request)
diff --git a/spec/graphql/types/query_type_spec.rb b/spec/graphql/types/query_type_spec.rb
index e941b980300..74e9522c16c 100644
--- a/spec/graphql/types/query_type_spec.rb
+++ b/spec/graphql/types/query_type_spec.rb
@@ -119,7 +119,7 @@ RSpec.describe GitlabSchema.types['Query'], feature_category: :shared do
describe 'container_repository field' do
subject { described_class.fields['containerRepository'] }
- it { is_expected.to have_graphql_type(Types::ContainerRepositoryDetailsType) }
+ it { is_expected.to have_graphql_type(Types::ContainerRegistry::ContainerRepositoryDetailsType) }
end
describe 'package field' do
diff --git a/spec/lib/gitlab/database/partitioning/time/daily_strategy_spec.rb b/spec/lib/gitlab/database/partitioning/time/daily_strategy_spec.rb
new file mode 100644
index 00000000000..394de593fb1
--- /dev/null
+++ b/spec/lib/gitlab/database/partitioning/time/daily_strategy_spec.rb
@@ -0,0 +1,346 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::Partitioning::Time::DailyStrategy, feature_category: :database do
+ let(:connection) { ApplicationRecord.connection }
+ let(:daily_strategy) do
+ described_class.new(model, partitioning_key, retain_for: retention_period, retain_non_empty_partitions: retain_data)
+ end
+
+ let(:retention_period) { nil }
+ let(:retain_data) { false }
+ let(:partitioning_key) { :created_at }
+ let(:table_name) { model.table_name }
+ let(:model) do
+ Class.new(ApplicationRecord) do
+ self.table_name = '_test_partitioned_test'
+ self.primary_key = :id
+ end
+ end
+
+ describe '#current_partitions' do
+ subject(:current_partitions) { daily_strategy.current_partitions }
+
+ before do
+ connection.execute(<<~SQL)
+ CREATE TABLE #{table_name}
+ (id serial not null, created_at timestamptz not null, PRIMARY KEY (id, created_at))
+ PARTITION BY RANGE (created_at);
+
+ CREATE TABLE #{Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA}._test_partitioned_test_00000000
+ PARTITION OF #{table_name}
+ FOR VALUES FROM (MINVALUE) TO ('2020-05-01');
+
+ CREATE TABLE #{Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA}._test_partitioned_test_20200501
+ PARTITION OF #{table_name}
+ FOR VALUES FROM ('2020-05-01') TO ('2020-05-02');
+ SQL
+ end
+
+ it 'detects both partitions' do
+ expect(current_partitions).to eq(
+ [
+ time_partition(table_name, nil, '2020-05-01', "#{model.table_name}_00000000"),
+ time_partition(table_name, '2020-05-01', '2020-05-02', "#{model.table_name}_20200501")
+ ])
+ end
+ end
+
+ describe '#missing_partitions', time_travel_to: '2020-05-04' do
+ subject(:missing_partitions) { daily_strategy.missing_partitions }
+
+ context 'with existing partitions' do
+ before do
+ connection.execute(<<~SQL)
+ CREATE TABLE #{table_name}
+ (id serial not null, created_at timestamptz not null, PRIMARY KEY (id, created_at))
+ PARTITION BY RANGE (created_at);
+
+ CREATE TABLE #{Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA}._test_partitioned_test_00000000
+ PARTITION OF #{table_name}
+ FOR VALUES FROM (MINVALUE) TO ('2020-05-01');
+
+ CREATE TABLE #{Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA}._test_partitioned_test_20200502
+ PARTITION OF #{table_name}
+ FOR VALUES FROM ('2020-05-02') TO ('2020-05-03');
+ SQL
+
+ # Insert some data, it doesn't make a difference
+ model.create!(created_at: Date.parse('2020-04-15'))
+ model.create!(created_at: Date.parse('2020-05-02'))
+ end
+
+ context 'when pruning partitions before 2020-05-02' do
+ let(:retention_period) { 1.day }
+
+ it 'does not include the missing partition from 2020-05-02 because it would be dropped' do
+ expect(missing_partitions).not_to include(
+ time_partition(table_name, '2020-05-01', '2020-05-02', "#{model.table_name}_20200501")
+ )
+ end
+
+ it 'detects the missing partition for 1 day ago (2020-05-03)' do
+ expect(missing_partitions).to include(
+ time_partition(table_name, '2020-05-03', '2020-05-04', "#{model.table_name}_20200503")
+ )
+ end
+ end
+
+ it 'detects the gap and the missing partition for 2020-05-01' do
+ expect(missing_partitions).to include(
+ time_partition(table_name, '2020-05-01', '2020-05-02', "#{model.table_name}_20200501")
+ )
+ end
+
+ it 'detects the missing partitions at the end of the range and expects a partition for 2020-05-03' do
+ expect(missing_partitions).to include(
+ time_partition(table_name, '2020-05-03', '2020-05-04', "#{model.table_name}_20200503")
+ )
+ end
+
+ it 'detects the missing partitions at the end of the range and expects a partition for 2020-05-05' do
+ expect(missing_partitions).to include(
+ time_partition(model.table_name, '2020-05-05', '2020-05-06', "#{model.table_name}_20200505")
+ )
+ end
+
+ it 'creates partitions 7 days out from now (2020-05-04 to 2020-05-10)' do
+ expect(missing_partitions).to include(
+ time_partition(table_name, '2020-05-04', '2020-05-05', "#{model.table_name}_20200504"),
+ time_partition(table_name, '2020-05-05', '2020-05-06', "#{model.table_name}_20200505"),
+ time_partition(table_name, '2020-05-06', '2020-05-07', "#{model.table_name}_20200506"),
+ time_partition(table_name, '2020-05-07', '2020-05-08', "#{model.table_name}_20200507"),
+ time_partition(table_name, '2020-05-08', '2020-05-09', "#{model.table_name}_20200508"),
+ time_partition(table_name, '2020-05-09', '2020-05-10', "#{model.table_name}_20200509"),
+ time_partition(table_name, '2020-05-10', '2020-05-11', "#{model.table_name}_20200510")
+ )
+ end
+
+ it 'detects all missing partitions' do
+ expect(missing_partitions.size).to eq(30)
+ end
+ end
+
+ context 'without existing partitions' do
+ before do
+ connection.execute(<<~SQL)
+ CREATE TABLE #{table_name}
+ (id serial not null, created_at timestamptz not null, PRIMARY KEY (id, created_at))
+ PARTITION BY RANGE (created_at);
+ SQL
+ end
+
+ context 'when pruning partitions before 2020-05-02' do
+ let(:retention_period) { 1.day }
+
+ it 'detects exactly the set of partitions from 2020-05-03 to 2020-05-31' do
+ days = (Date.parse('2020-05-03')..Date.parse('2020-06-01')).map(&:to_s)
+ expected = days[..-2].zip(days.drop(1)).map do |(from, to)|
+ partition_name = "#{model.table_name}_#{Date.parse(from).strftime('%Y%m%d')}"
+ time_partition(model.table_name, from, to, partition_name)
+ end
+
+ expect(missing_partitions).to match_array(expected)
+ end
+ end
+
+ it 'detects the missing catch-all partition at the beginning' do
+ expect(missing_partitions).to include(
+ time_partition(table_name, nil, '2020-05-04', "#{model.table_name}_00000000")
+ )
+ end
+
+ it 'detects the missing partition for today and expects a partition for 2020-05-04' do
+ expect(missing_partitions).to include(
+ time_partition(table_name, '2020-05-04', '2020-05-05', "#{model.table_name}_20200504")
+ )
+ end
+
+ it 'creates partitions 7 days out from now (2020-05-04 through 2020-05-10)' do
+ expect(missing_partitions).to include(
+ time_partition(table_name, '2020-05-04', '2020-05-05', "#{model.table_name}_20200504"),
+ time_partition(table_name, '2020-05-05', '2020-05-06', "#{model.table_name}_20200505"),
+ time_partition(table_name, '2020-05-06', '2020-05-07', "#{model.table_name}_20200506"),
+ time_partition(table_name, '2020-05-07', '2020-05-08', "#{model.table_name}_20200507"),
+ time_partition(table_name, '2020-05-08', '2020-05-09', "#{model.table_name}_20200508"),
+ time_partition(table_name, '2020-05-09', '2020-05-10', "#{model.table_name}_20200509"),
+ time_partition(table_name, '2020-05-10', '2020-05-11', "#{model.table_name}_20200510")
+ )
+ end
+
+ it 'detects all missing partitions' do
+ expect(missing_partitions.size).to eq(29)
+ end
+ end
+
+ context 'with a regular partition but no catchall (MINVALUE, to) partition' do
+ before do
+ connection.execute(<<~SQL)
+ CREATE TABLE #{table_name}
+ (id serial not null, created_at timestamptz not null, PRIMARY KEY (id, created_at))
+ PARTITION BY RANGE (created_at);
+
+ CREATE TABLE #{Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA}._test_partitioned_test_20200501
+ PARTITION OF #{table_name}
+ FOR VALUES FROM ('2020-05-01') TO ('2020-05-02');
+ SQL
+ end
+
+ it 'detects a missing catch-all partition to add before the existing partition' do
+ expect(missing_partitions).to include(
+ time_partition(table_name, nil, '2020-05-01', "#{model.table_name}_00000000")
+ )
+ end
+ end
+ end
+
+ describe '#extra_partitions', time_travel_to: '2020-05-04' do
+ subject(:extra_partitions) { daily_strategy.extra_partitions }
+
+ describe 'with existing partitions' do
+ before do
+ ActiveRecord::Base.connection.execute(<<~SQL)
+ CREATE TABLE #{table_name}
+ (id serial not null, created_at timestamptz not null, PRIMARY KEY (id, created_at))
+ PARTITION BY RANGE (created_at);
+
+ CREATE TABLE #{Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA}._test_partitioned_test_00000000
+ PARTITION OF #{table_name}
+ FOR VALUES FROM (MINVALUE) TO ('2020-05-01');
+
+ CREATE TABLE #{Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA}._test_partitioned_test_20200501
+ PARTITION OF #{table_name}
+ FOR VALUES FROM ('2020-05-01') TO ('2020-05-02');
+
+ CREATE TABLE #{Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA}._test_partitioned_test_20200502
+ PARTITION OF #{table_name}
+ FOR VALUES FROM ('2020-05-02') TO ('2020-05-03')
+ SQL
+ end
+
+ context 'without a time retention policy' do
+ it 'has no extra partitions to prune' do
+ expect(extra_partitions).to be_empty
+ end
+ end
+
+ context 'with a time retention policy that excludes no partitions' do
+ let(:retention_period) { 4.days }
+
+ it 'has no extra partitions to prune' do
+ expect(extra_partitions).to be_empty
+ end
+ end
+
+ context 'with a time retention policy of 3 days' do
+ let(:retention_period) { 3.days }
+
+ it 'prunes the unbounded partition ending 2020-05-01' do
+ min_value = time_partition(table_name, nil, '2020-05-01', "#{model.table_name}_00000000")
+
+ expect(extra_partitions).to contain_exactly(min_value)
+ end
+ end
+
+ context 'with a time retention policy of 2 days' do
+ let(:retention_period) { 2.days }
+
+ it 'prunes the unbounded partition and the partition for min value to 2020-05-01' do
+ expect(extra_partitions).to contain_exactly(
+ time_partition(table_name, nil, '2020-05-01', "#{model.table_name}_00000000"),
+ time_partition(table_name, '2020-05-01', '2020-05-02', "#{model.table_name}_20200501")
+ )
+ end
+
+ context 'when the retain_non_empty_partitions is true' do
+ let(:retain_data) { true }
+
+ it 'prunes empty partitions' do
+ expect(extra_partitions).to contain_exactly(
+ time_partition(table_name, nil, '2020-05-01', "#{model.table_name}_00000000"),
+ time_partition(table_name, '2020-05-01', '2020-05-02', "#{model.table_name}_20200501")
+ )
+ end
+
+ it 'does not prune non-empty partitions' do
+ # inserting one record into _test_partitioned_test_20200501
+ connection.execute("INSERT INTO #{table_name} (created_at) VALUES (('2020-05-01'))")
+
+ expect(extra_partitions).to contain_exactly(
+ time_partition(table_name, nil, '2020-05-01', "#{model.table_name}_00000000")
+ )
+ end
+ end
+ end
+
+ context 'with a time retention policy of 1 day' do
+ let(:retention_period) { 1.day }
+
+ it 'prunes the unbounded partition and the partitions for 2020-05-01 and 2020-05-02' do
+ expect(extra_partitions).to contain_exactly(
+ time_partition(table_name, nil, '2020-05-01', "#{model.table_name}_00000000"),
+ time_partition(table_name, '2020-05-01', '2020-05-02', "#{model.table_name}_20200501"),
+ time_partition(table_name, '2020-05-02', '2020-05-03', "#{model.table_name}_20200502")
+ )
+ end
+
+ context 'when the retain_non_empty_partitions is true' do
+ let(:retain_data) { true }
+
+ it 'prunes empty partitions' do
+ expect(extra_partitions).to contain_exactly(
+ time_partition(table_name, nil, '2020-05-01', "#{model.table_name}_00000000"),
+ time_partition(table_name, '2020-05-01', '2020-05-02', "#{model.table_name}_20200501"),
+ time_partition(table_name, '2020-05-02', '2020-05-03', "#{model.table_name}_20200502")
+ )
+ end
+
+ it 'does not prune non-empty partitions' do
+ # inserting one record into _test_partitioned_test_20200501
+ connection.execute("INSERT INTO #{table_name} (created_at) VALUES (('2020-05-01'))")
+
+ expect(extra_partitions).to contain_exactly(
+ time_partition(table_name, nil, '2020-05-01', "#{model.table_name}_00000000"),
+ time_partition(table_name, '2020-05-02', '2020-05-03', "#{model.table_name}_20200502")
+ )
+ end
+ end
+ end
+ end
+ end
+
+ describe '#partition_name' do
+ let(:from) { Date.parse('2020-05-01 00:00:00') }
+ let(:to) { Date.parse('2020-05-02 00:00:00') }
+
+ subject(:partition_name) { daily_strategy.partition_name(from) }
+
+ it 'uses table_name as prefix' do
+ expect(partition_name).to start_with(table_name)
+ end
+
+ it 'uses Year-Month-Day (from) as suffix' do
+ expect(partition_name).to end_with("_20200501")
+ end
+
+ context 'without from date' do
+ let(:from) { nil }
+
+ it 'uses 00000000 as suffix for first partition' do
+ expect(partition_name).to end_with("_00000000")
+ end
+ end
+ end
+
+ private
+
+ def time_partition(table_name, lower_bound, upper_bound, partition_name)
+ Gitlab::Database::Partitioning::TimePartition.new(
+ table_name,
+ lower_bound,
+ upper_bound,
+ partition_name: partition_name
+ )
+ end
+end
diff --git a/spec/lib/gitlab/import_export/project/relation_factory_spec.rb b/spec/lib/gitlab/import_export/project/relation_factory_spec.rb
index c3fa9e1ea90..54bf741f0a2 100644
--- a/spec/lib/gitlab/import_export/project/relation_factory_spec.rb
+++ b/spec/lib/gitlab/import_export/project/relation_factory_spec.rb
@@ -173,7 +173,7 @@ RSpec.describe Gitlab::ImportExport::Project::RelationFactory, :use_clean_rails_
expect(created_object.target_project).to equal(project)
end
- it 'has MWPS set to false' do
+ it 'has auto merge set to false' do
expect(created_object.merge_when_pipeline_succeeds).to eq(false)
end
diff --git a/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
index df2861f67d2..b6590701544 100644
--- a/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
@@ -313,7 +313,7 @@ RSpec.describe Gitlab::ImportExport::Project::TreeRestorer, feature_category: :i
end
end
- it 'sets MWPS to false for all merge requests' do
+ it 'sets auto merge to false for all merge requests' do
MergeRequest.find_each do |merge_request|
expect(merge_request.merge_when_pipeline_succeeds).to eq(false)
end
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index 8ae6d5c56a9..c858f918c88 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -1822,7 +1822,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep, feature_category:
describe 'auto merge' do
context 'when auto merge is enabled' do
- let_it_be_with_reload(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
+ let_it_be_with_reload(:merge_request) { create(:merge_request, :merge_when_checks_pass) }
let_it_be_with_reload(:pipeline) do
create(:ci_pipeline, :running,
project: merge_request.source_project, ref: merge_request.source_branch, sha: merge_request.diff_head_sha)
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 549535be559..48d3c3345c5 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -2312,18 +2312,10 @@ RSpec.describe MergeRequest, factory_default: :keep, feature_category: :code_rev
describe "#auto_merge_strategy" do
subject { merge_request.auto_merge_strategy }
- let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
+ let(:merge_request) { create(:merge_request, :merge_when_checks_pass) }
it { is_expected.to eq('merge_when_checks_pass') }
- context 'when merge_when_checks_pass is false' do
- before do
- stub_feature_flags(merge_when_checks_pass: false)
- end
-
- it { is_expected.to eq('merge_when_pipeline_succeeds') }
- end
-
context 'when auto merge is disabled' do
let(:merge_request) { create(:merge_request) }
@@ -2334,17 +2326,9 @@ RSpec.describe MergeRequest, factory_default: :keep, feature_category: :code_rev
describe '#default_auto_merge_strategy' do
subject { merge_request.default_auto_merge_strategy }
- let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
+ let(:merge_request) { create(:merge_request, :merge_when_checks_pass) }
it { is_expected.to eq(AutoMergeService::STRATEGY_MERGE_WHEN_CHECKS_PASS) }
-
- context 'when merge_when_checks_pass feature flag is off' do
- before do
- stub_feature_flags(merge_when_checks_pass: false)
- end
-
- it { is_expected.to eq(AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS) }
- end
end
describe '#committers' do
@@ -3938,7 +3922,6 @@ RSpec.describe MergeRequest, factory_default: :keep, feature_category: :code_rev
where(:auto_merge_strategy, :skip_checks) do
'' | false
- AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS | false
AutoMergeService::STRATEGY_MERGE_WHEN_CHECKS_PASS | true
end
@@ -5845,7 +5828,7 @@ RSpec.describe MergeRequest, factory_default: :keep, feature_category: :code_rev
let!(:merge_request1) do
create(
:merge_request,
- :merge_when_pipeline_succeeds,
+ :merge_when_checks_pass,
target_project: project,
target_branch: 'master',
source_project: project,
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index 66fb86660e1..3366fdf713d 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -1583,10 +1583,10 @@ RSpec.describe API::MergeRequests, :aggregate_failures, feature_category: :sourc
end
context 'merge_user' do
- context 'when MR is set to MWPS' do
- let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds, source_project: project, target_project: project) }
+ context 'when MR is set to auto merge' do
+ let(:merge_request) { create(:merge_request, :merge_when_checks_pass, source_project: project, target_project: project) }
- it 'returns user who set MWPS' do
+ it 'returns user who set to auto merge' do
get api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user)
expect(response).to have_gitlab_http_status(:ok)
@@ -3179,45 +3179,6 @@ RSpec.describe API::MergeRequests, :aggregate_failures, feature_category: :sourc
expect(response).to have_gitlab_http_status(:ok)
end
- context 'when merge_when_checks_pass is off' do
- before do
- stub_feature_flags(merge_when_checks_pass: false)
- end
-
- it_behaves_like 'merging with auto merge strategies'
-
- it 'does not enable auto merge if MR is not mergeable and only_allow_merge_if_pipeline_succeeds is true' do
- allow_any_instance_of(MergeRequest)
- .to receive_messages(
- head_pipeline: pipeline,
- diff_head_pipeline: pipeline
- )
-
- merge_request.update!(title: 'Draft: 1234')
-
- project.update_attribute(:only_allow_merge_if_pipeline_succeeds, true)
-
- put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user), params: { merge_when_pipeline_succeeds: true }
-
- expect(response).to have_gitlab_http_status(:method_not_allowed)
- expect(merge_request.reload.state).to eq('opened')
- end
-
- context 'when the pipeline failed' do
- let(:pipeline) { create(:ci_pipeline, :failed, project: project) }
-
- it 'does not enable auto merge if the pipeline failed and only_allow_merge_if_pipeline_succeeds is true' do
- allow_any_instance_of(MergeRequest).to receive_messages(head_pipeline: pipeline, diff_head_pipeline: pipeline)
- project.update_attribute(:only_allow_merge_if_pipeline_succeeds, true)
-
- put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user), params: { merge_when_pipeline_succeeds: true }
-
- expect(response).to have_gitlab_http_status(:method_not_allowed)
- expect(merge_request.reload.state).to eq('opened')
- end
- end
- end
-
it_behaves_like 'merging with auto merge strategies'
it 'enables auto merge if the MR is not mergeable and only_allow_merge_if_pipeline_succeeds is true' do
@@ -3990,7 +3951,7 @@ RSpec.describe API::MergeRequests, :aggregate_failures, feature_category: :sourc
describe 'POST :id/merge_requests/:merge_request_iid/cancel_merge_when_pipeline_succeeds' do
before do
- ::AutoMergeService.new(merge_request.target_project, user).execute(merge_request, AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS)
+ ::AutoMergeService.new(merge_request.target_project, user).execute(merge_request, AutoMergeService::STRATEGY_MERGE_WHEN_CHECKS_PASS)
end
it 'removes the merge_when_pipeline_succeeds status' do
diff --git a/spec/serializers/merge_request_poll_widget_entity_spec.rb b/spec/serializers/merge_request_poll_widget_entity_spec.rb
index 878bb8b0086..2d2b9282173 100644
--- a/spec/serializers/merge_request_poll_widget_entity_spec.rb
+++ b/spec/serializers/merge_request_poll_widget_entity_spec.rb
@@ -49,21 +49,11 @@ RSpec.describe MergeRequestPollWidgetEntity do
end
context 'when auto merge is enabled' do
- let(:resource) { create(:merge_request, :merge_when_pipeline_succeeds) }
+ let(:resource) { create(:merge_request, :merge_when_checks_pass) }
it 'returns auto merge related information' do
expect(subject[:auto_merge_strategy]).to eq('merge_when_checks_pass')
end
-
- context 'when merge_when_checks_pass is false' do
- before do
- stub_feature_flags(merge_when_checks_pass: false)
- end
-
- it 'returns auto merge related information' do
- expect(subject[:auto_merge_strategy]).to eq('merge_when_pipeline_succeeds')
- end
- end
end
context 'when auto merge is not enabled' do
@@ -83,16 +73,6 @@ RSpec.describe MergeRequestPollWidgetEntity do
it 'returns available auto merge strategies' do
expect(subject[:available_auto_merge_strategies]).to eq(%w[merge_when_checks_pass])
end
-
- context 'when the merge_when_checks_pass is false' do
- before do
- stub_feature_flags(merge_when_checks_pass: false)
- end
-
- it 'returns available auto merge strategies' do
- expect(subject[:available_auto_merge_strategies]).to eq(%w[merge_when_pipeline_succeeds])
- end
- end
end
describe 'squash defaults for projects' do
diff --git a/spec/services/auto_merge/base_service_spec.rb b/spec/services/auto_merge/base_service_spec.rb
index 8022f81f290..3323fac76dd 100644
--- a/spec/services/auto_merge/base_service_spec.rb
+++ b/spec/services/auto_merge/base_service_spec.rb
@@ -56,32 +56,6 @@ RSpec.describe AutoMerge::BaseService, feature_category: :code_review_workflow d
end
end
- context 'when strategy is merge when pipeline succeeds' do
- let(:service) { AutoMerge::MergeWhenPipelineSucceedsService.new(project, user) }
-
- before do
- pipeline = build(:ci_pipeline)
- allow(merge_request).to receive(:diff_head_pipeline) { pipeline }
- end
-
- it 'sets the auto merge strategy' do
- subject
-
- merge_request.reload
- expect(merge_request.auto_merge_strategy).to eq(AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS)
- end
-
- it 'returns activated strategy name' do
- is_expected.to eq(AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS.to_sym)
- end
-
- it 'calls AutoMergeProcessWorker' do
- expect(AutoMergeProcessWorker).to receive(:perform_async).with({ 'merge_request_id' => merge_request.id }).once
-
- subject
- end
- end
-
context 'when failed to save merge request' do
before do
allow(merge_request).to receive(:save!) { raise ActiveRecord::RecordInvalid }
@@ -133,7 +107,7 @@ RSpec.describe AutoMerge::BaseService, feature_category: :code_review_workflow d
describe '#update' do
subject { service.update(merge_request) } # rubocop:disable Rails/SaveBang
- let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
+ let(:merge_request) { create(:merge_request, :merge_when_checks_pass) }
context 'when merge params are specified' do
let(:params) do
@@ -178,7 +152,7 @@ RSpec.describe AutoMerge::BaseService, feature_category: :code_review_workflow d
'should_remove_source_branch' => false,
'commit_message' => "Merge branch 'patch-12' into 'master'",
'squash_commit_message' => "Update README.md",
- 'auto_merge_strategy' => 'merge_when_pipeline_succeeds'
+ 'auto_merge_strategy' => 'merge_when_checks_pass'
})
end
@@ -207,7 +181,7 @@ RSpec.describe AutoMerge::BaseService, feature_category: :code_review_workflow d
describe '#cancel' do
subject { service.cancel(merge_request) }
- let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
+ let(:merge_request) { create(:merge_request, :merge_when_checks_pass) }
it_behaves_like 'Canceled or Dropped'
@@ -253,7 +227,7 @@ RSpec.describe AutoMerge::BaseService, feature_category: :code_review_workflow d
describe '#abort' do
subject { service.abort(merge_request, reason) }
- let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
+ let(:merge_request) { create(:merge_request, :merge_when_checks_pass) }
let(:reason) { 'an error' }
it_behaves_like 'Canceled or Dropped'
diff --git a/spec/services/auto_merge/merge_when_checks_pass_service_spec.rb b/spec/services/auto_merge/merge_when_checks_pass_service_spec.rb
index 0b0dd9a3965..ce439596ccc 100644
--- a/spec/services/auto_merge/merge_when_checks_pass_service_spec.rb
+++ b/spec/services/auto_merge/merge_when_checks_pass_service_spec.rb
@@ -15,12 +15,6 @@ RSpec.describe AutoMerge::MergeWhenChecksPassService, feature_category: :code_re
describe '#available_for?' do
subject { service.available_for?(mr_merge_if_green_enabled) }
- let(:feature_flag) { true }
-
- before do
- stub_feature_flags(merge_when_checks_pass: feature_flag)
- end
-
context 'when immediately mergeable' do
context 'when a non active pipeline' do
before do
@@ -47,24 +41,12 @@ RSpec.describe AutoMerge::MergeWhenChecksPassService, feature_category: :code_re
end
end
- context 'when merge when checks pass flag is off' do
- let(:feature_flag) { false }
-
- it { is_expected.to eq false }
- end
-
context 'when draft status' do
before do
mr_merge_if_green_enabled.update!(title: 'Draft: check')
end
it { is_expected.to eq true }
-
- context 'when merge_when_checks_pass flag is off' do
- let(:feature_flag) { false }
-
- it { is_expected.to eq false }
- end
end
context 'when discussions open' do
@@ -75,12 +57,6 @@ RSpec.describe AutoMerge::MergeWhenChecksPassService, feature_category: :code_re
end
it { is_expected.to eq true }
-
- context 'when merge_when_checks_pass flag is off' do
- let(:feature_flag) { false }
-
- it { is_expected.to eq false }
- end
end
context 'when pipline is active' do
@@ -94,12 +70,6 @@ RSpec.describe AutoMerge::MergeWhenChecksPassService, feature_category: :code_re
end
it { is_expected.to eq true }
-
- context 'when merge_when_checks_pass flag is off' do
- let(:feature_flag) { false }
-
- it { is_expected.to eq false }
- end
end
context 'when the user does not have permission to merge' do
diff --git a/spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb b/spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb
index d9b8a10e338..ea89bb8cd62 100644
--- a/spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb
+++ b/spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb
@@ -5,12 +5,6 @@ require 'spec_helper'
RSpec.describe AutoMerge::MergeWhenPipelineSucceedsService, feature_category: :code_review_workflow do
include_context 'for auto_merge strategy context'
- let(:merge_when_checks_pass_ff) { false }
-
- before do
- stub_feature_flags(merge_when_checks_pass: merge_when_checks_pass_ff)
- end
-
describe "#available_for?" do
subject { service.available_for?(mr_merge_if_green_enabled) }
@@ -27,19 +21,7 @@ RSpec.describe AutoMerge::MergeWhenPipelineSucceedsService, feature_category: :c
mr_merge_if_green_enabled.update_head_pipeline
end
- it { is_expected.to be_truthy }
-
- context 'when merge when checks ff is true' do
- let(:merge_when_checks_pass_ff) { true }
-
- it { is_expected.to be_falsey }
- end
-
- it 'memoizes the result' do
- expect(mr_merge_if_green_enabled).to receive(:can_be_merged_by?).once.and_call_original
-
- 2.times { is_expected.to be_truthy }
- end
+ it { is_expected.to be_falsey }
context 'when the head pipeline succeeded' do
let(:pipeline_status) { :success }
diff --git a/spec/services/auto_merge_service_spec.rb b/spec/services/auto_merge_service_spec.rb
index 50dec471632..070e237f8e7 100644
--- a/spec/services/auto_merge_service_spec.rb
+++ b/spec/services/auto_merge_service_spec.rb
@@ -52,17 +52,7 @@ RSpec.describe AutoMergeService, feature_category: :code_review_workflow do
is_expected.to include('merge_when_checks_pass')
end
- context 'when merge_when_checks_pass is off' do
- before do
- stub_feature_flags(merge_when_checks_pass: false)
- end
-
- it 'returns available strategies' do
- is_expected.to include('merge_when_pipeline_succeeds')
- end
- end
-
- context 'when the head piipeline succeeded' do
+ context 'when the head pipeline succeeded' do
let(:pipeline_status) { :success }
it 'returns available strategies' do
@@ -157,19 +147,15 @@ RSpec.describe AutoMergeService, feature_category: :code_review_workflow do
end
end
- context 'when the strategy is MWPS and merge_when_checks_pass is off' do
- before do
- stub_feature_flags(merge_when_checks_pass: false)
- end
-
+ context 'when the strategy is MWPS' do
let(:strategy) { AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS }
- it 'delegates to a relevant service instance' do
+ it 'does not call execute and returns failed' do
expect_next_instance_of(AutoMerge::MergeWhenPipelineSucceedsService) do |service|
- expect(service).to receive(:execute).with(merge_request)
+ expect(service).not_to receive(:execute).with(merge_request)
end
- subject
+ expect(subject).to eq(:failed)
end
end
@@ -213,10 +199,6 @@ RSpec.describe AutoMergeService, feature_category: :code_review_workflow do
context 'when the merge request is MWPS' do
let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
- before do
- stub_feature_flags(merge_when_checks_pass: false)
- end
-
it 'delegates to a relevant service instance' do
expect_next_instance_of(AutoMerge::MergeWhenPipelineSucceedsService) do |service|
expect(service).to receive(:update).with(merge_request)
@@ -254,10 +236,6 @@ RSpec.describe AutoMergeService, feature_category: :code_review_workflow do
context 'when the merge request is MWPS' do
let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
- before do
- stub_feature_flags(merge_when_checks_pass: false)
- end
-
it 'delegates to a relevant service instance' do
expect_next_instance_of(AutoMerge::MergeWhenPipelineSucceedsService) do |service|
expect(service).to receive(:process).with(merge_request)
@@ -294,10 +272,6 @@ RSpec.describe AutoMergeService, feature_category: :code_review_workflow do
context 'when the merge request is MWPS' do
let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
- before do
- stub_feature_flags(merge_when_checks_pass: false)
- end
-
it 'delegates to a relevant service instance' do
expect_next_instance_of(AutoMerge::MergeWhenPipelineSucceedsService) do |service|
expect(service).to receive(:cancel).with(merge_request)
@@ -338,10 +312,6 @@ RSpec.describe AutoMergeService, feature_category: :code_review_workflow do
context 'when the merge request is MWPS' do
let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
- before do
- stub_feature_flags(merge_when_checks_pass: false)
- end
-
it 'delegates to a relevant service instance' do
expect_next_instance_of(AutoMerge::MergeWhenPipelineSucceedsService) do |service|
expect(service).to receive(:abort).with(merge_request, error)
diff --git a/spec/services/discussions/resolve_service_spec.rb b/spec/services/discussions/resolve_service_spec.rb
index 79b0a4bbb7e..15fcaedd2bc 100644
--- a/spec/services/discussions/resolve_service_spec.rb
+++ b/spec/services/discussions/resolve_service_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Discussions::ResolveService, feature_category: :code_review_workf
describe '#execute' do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { create(:user, developer_of: project) }
- let_it_be(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds, source_project: project) }
+ let_it_be(:merge_request) { create(:merge_request, :merge_when_checks_pass, source_project: project) }
let(:discussion) { create(:diff_note_on_merge_request, noteable: merge_request, project: project).to_discussion }
let(:service) { described_class.new(project, user, one_or_more_discussions: discussion) }
@@ -46,18 +46,6 @@ RSpec.describe Discussions::ResolveService, feature_category: :code_review_workf
.to publish_event(MergeRequests::DiscussionsResolvedEvent)
.with(current_user_id: user.id, merge_request_id: merge_request.id)
end
-
- context 'when merge_when_checks_pass is false' do
- before do
- stub_feature_flags(merge_when_checks_pass: false)
- end
-
- it 'schedules an auto-merge' do
- expect(AutoMergeProcessWorker).to receive(:perform_async)
-
- service.execute
- end
- end
end
context 'when not all discussions are resolved' do
@@ -66,18 +54,6 @@ RSpec.describe Discussions::ResolveService, feature_category: :code_review_workf
it 'does not publish the discussions resolved event' do
expect { service.execute }.not_to publish_event(MergeRequests::DiscussionsResolvedEvent)
end
-
- context 'when merge_when_checks_pass is false' do
- before do
- stub_feature_flags(merge_when_checks_pass: false)
- end
-
- it 'schedules an auto-merge' do
- expect(AutoMergeProcessWorker).to receive(:perform_async)
-
- described_class.new(project, user, one_or_more_discussions: [discussion, other_discussion]).execute
- end
- end
end
it 'sends GraphQL triggers' do
diff --git a/spec/services/discussions/unresolve_service_spec.rb b/spec/services/discussions/unresolve_service_spec.rb
index a9eb4d8a992..8b2843bb677 100644
--- a/spec/services/discussions/unresolve_service_spec.rb
+++ b/spec/services/discussions/unresolve_service_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Discussions::UnresolveService, feature_category: :code_review_wor
describe "#execute" do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { create(:user, developer_of: project) }
- let_it_be(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds, source_project: project) }
+ let_it_be(:merge_request) { create(:merge_request, :merge_when_checks_pass, source_project: project) }
let(:discussion) { create(:diff_note_on_merge_request, noteable: merge_request, project: project).to_discussion }
diff --git a/spec/services/merge_requests/close_service_spec.rb b/spec/services/merge_requests/close_service_spec.rb
index f140d3bfe63..c2c27ff206e 100644
--- a/spec/services/merge_requests/close_service_spec.rb
+++ b/spec/services/merge_requests/close_service_spec.rb
@@ -58,7 +58,7 @@ RSpec.describe MergeRequests::CloseService, feature_category: :code_review_workf
end
context 'when auto merge is enabled' do
- let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
+ let(:merge_request) { create(:merge_request, :merge_when_checks_pass) }
it 'cancels the auto merge' do
expect(@merge_request).not_to be_auto_merge_enabled
diff --git a/spec/services/merge_requests/merge_orchestration_service_spec.rb b/spec/services/merge_requests/merge_orchestration_service_spec.rb
index 020d433352c..fa95c72b826 100644
--- a/spec/services/merge_requests/merge_orchestration_service_spec.rb
+++ b/spec/services/merge_requests/merge_orchestration_service_spec.rb
@@ -119,16 +119,6 @@ RSpec.describe MergeRequests::MergeOrchestrationService, feature_category: :code
it 'fetches preferred auto merge strategy' do
is_expected.to eq(AutoMergeService::STRATEGY_MERGE_WHEN_CHECKS_PASS)
end
-
- context 'when merge_when_checks_pass feature is off' do
- before do
- stub_feature_flags(merge_when_checks_pass: false)
- end
-
- it 'fetches preferred auto merge strategy' do
- is_expected.to eq(AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS)
- end
- end
end
context 'when merge request cannot be merged automatically' do
diff --git a/spec/services/merge_requests/post_merge_service_spec.rb b/spec/services/merge_requests/post_merge_service_spec.rb
index 9d5b53be55e..7da872e1a25 100644
--- a/spec/services/merge_requests/post_merge_service_spec.rb
+++ b/spec/services/merge_requests/post_merge_service_spec.rb
@@ -198,11 +198,11 @@ RSpec.describe MergeRequests::PostMergeService, feature_category: :code_review_w
let(:params) { { delete_source_branch: true } }
it 'aborts auto merges' do
- mr_1 = create(:merge_request, :merge_when_pipeline_succeeds, target_branch: merge_request.source_branch,
+ mr_1 = create(:merge_request, :merge_when_checks_pass, target_branch: merge_request.source_branch,
source_branch: "test", source_project: merge_request.project)
mr_2 = create(:merge_request, :merge_when_checks_pass, target_branch: merge_request.source_branch,
source_branch: "feature", source_project: merge_request.project)
- mr_3 = create(:merge_request, :merge_when_pipeline_succeeds, target_branch: 'feature',
+ mr_3 = create(:merge_request, :merge_when_checks_pass, target_branch: 'feature',
source_branch: 'second', source_project: merge_request.project)
expect(merge_request.source_project.merge_requests.with_auto_merge_enabled).to contain_exactly(mr_1, mr_2, mr_3)
@@ -213,30 +213,11 @@ RSpec.describe MergeRequests::PostMergeService, feature_category: :code_review_w
context 'when source branch is not be deleted' do
it 'does not abort any auto merges' do
- mr_1 = create(:merge_request, :merge_when_pipeline_succeeds, target_branch: merge_request.source_branch,
+ mr_1 = create(:merge_request, :merge_when_checks_pass, target_branch: merge_request.source_branch,
source_branch: "test", source_project: merge_request.project)
mr_2 = create(:merge_request, :merge_when_checks_pass, target_branch: merge_request.source_branch,
source_branch: "feature", source_project: merge_request.project)
- mr_3 = create(:merge_request, :merge_when_pipeline_succeeds, target_branch: 'feature',
- source_branch: 'second', source_project: merge_request.project)
-
- expect(merge_request.source_project.merge_requests.with_auto_merge_enabled).to contain_exactly(mr_1, mr_2, mr_3)
- subject
- expect(merge_request.source_project.merge_requests.with_auto_merge_enabled).to contain_exactly(mr_1, mr_2, mr_3)
- end
- end
-
- context 'when merge_when_checks_pass is disabled' do
- before do
- stub_feature_flags(merge_when_checks_pass: false)
- end
-
- it 'does not aborts any auto merges' do
- mr_1 = create(:merge_request, :merge_when_pipeline_succeeds, target_branch: merge_request.source_branch,
- source_branch: "test", source_project: merge_request.project)
- mr_2 = create(:merge_request, :merge_when_checks_pass, target_branch: merge_request.source_branch,
- source_branch: "feature", source_project: merge_request.project)
- mr_3 = create(:merge_request, :merge_when_pipeline_succeeds, target_branch: 'feature',
+ mr_3 = create(:merge_request, :merge_when_checks_pass, target_branch: 'feature',
source_branch: 'second', source_project: merge_request.project)
expect(merge_request.source_project.merge_requests.with_auto_merge_enabled).to contain_exactly(mr_1, mr_2, mr_3)
diff --git a/spec/services/merge_requests/push_options_handler_service_spec.rb b/spec/services/merge_requests/push_options_handler_service_spec.rb
index 2690714e7fa..0b6c9bcb537 100644
--- a/spec/services/merge_requests/push_options_handler_service_spec.rb
+++ b/spec/services/merge_requests/push_options_handler_service_spec.rb
@@ -139,21 +139,6 @@ RSpec.describe MergeRequests::PushOptionsHandlerService, feature_category: :sour
expect(last_mr.merge_user).to eq(user1)
expect(last_mr.merge_params['sha']).to eq(change[:newrev])
end
-
- context 'when merge_when_checks_pass is false' do
- before do
- stub_feature_flags(merge_when_checks_pass: false)
- end
-
- it 'sets auto_merge_enabled' do
- service.execute
-
- expect(last_mr.auto_merge_enabled).to eq(true)
- expect(last_mr.auto_merge_strategy).to eq(AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS)
- expect(last_mr.merge_user).to eq(user1)
- expect(last_mr.merge_params['sha']).to eq(change[:newrev])
- end
- end
end
shared_examples_for 'a service that can remove the source branch when it is merged' do
diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb
index b0a449e5674..307d738f120 100644
--- a/spec/services/merge_requests/refresh_service_spec.rb
+++ b/spec/services/merge_requests/refresh_service_spec.rb
@@ -26,7 +26,7 @@ RSpec.describe MergeRequests::RefreshService, feature_category: :code_review_wor
target_branch: 'feature',
target_project: @project,
auto_merge_enabled: true,
- auto_merge_strategy: AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS,
+ auto_merge_strategy: AutoMergeService::STRATEGY_MERGE_WHEN_CHECKS_PASS,
merge_user: @user
)
@@ -37,7 +37,7 @@ RSpec.describe MergeRequests::RefreshService, feature_category: :code_review_wor
target_branch: 'test',
target_project: @project,
auto_merge_enabled: true,
- auto_merge_strategy: AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS,
+ auto_merge_strategy: AutoMergeService::STRATEGY_MERGE_WHEN_CHECKS_PASS,
merge_user: @user
)
@@ -543,6 +543,15 @@ RSpec.describe MergeRequests::RefreshService, feature_category: :code_review_wor
context 'With merged MR that contains the same SHA' do
before do
+ @merge_request.head_pipeline = create(
+ :ci_pipeline,
+ :success,
+ project: @merge_request.source_project,
+ ref: @merge_request.source_branch,
+ sha: @merge_request.diff_head_sha)
+
+ @merge_request.update_head_pipeline
+
# Merged via UI
MergeRequests::MergeService
.new(project: @merge_request.target_project, current_user: @user, params: { sha: @merge_request.diff_head_sha })
@@ -1012,7 +1021,7 @@ RSpec.describe MergeRequests::RefreshService, feature_category: :code_review_wor
target_project: project,
merge_user: user,
auto_merge_enabled: true,
- auto_merge_strategy: AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS
+ auto_merge_strategy: AutoMergeService::STRATEGY_MERGE_WHEN_CHECKS_PASS
)
end
@@ -1030,7 +1039,7 @@ RSpec.describe MergeRequests::RefreshService, feature_category: :code_review_wor
merge_request.reload
end
- it 'aborts MWPS for merge requests' do
+ it 'aborts auto merge for merge requests' do
expect(merge_request.auto_merge_enabled?).to be_falsey
expect(merge_request.merge_user).to be_nil
end
@@ -1038,7 +1047,7 @@ RSpec.describe MergeRequests::RefreshService, feature_category: :code_review_wor
context 'when merge params contains up-to-date sha' do
let(:merge_sha) { newrev }
- it 'maintains MWPS for merge requests' do
+ it 'maintains auto merge for merge requests' do
expect(merge_request.auto_merge_enabled?).to be_truthy
expect(merge_request.merge_user).to eq(user)
end
diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb
index 55435bb3fcd..6a3b195f00d 100644
--- a/spec/services/merge_requests/update_service_spec.rb
+++ b/spec/services/merge_requests/update_service_spec.rb
@@ -857,7 +857,7 @@ RSpec.describe MergeRequests::UpdateService, :mailer, feature_category: :code_re
context 'when auto merge is enabled and target branch changed' do
before do
- AutoMergeService.new(project, user, { sha: merge_request.diff_head_sha }).execute(merge_request, AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS)
+ AutoMergeService.new(project, user, { sha: merge_request.diff_head_sha }).execute(merge_request, AutoMergeService::STRATEGY_MERGE_WHEN_CHECKS_PASS)
end
it 'calls MergeRequests::ResolveTodosService#async_execute' do
@@ -920,16 +920,6 @@ RSpec.describe MergeRequests::UpdateService, :mailer, feature_category: :code_re
end
end
- context 'when merge_when_checks_pass is disabled' do
- before do
- stub_feature_flags(merge_when_checks_pass: false)
- end
-
- it 'does not publish a DraftStateChangeEvent' do
- expect { update_merge_request(title: 'New title') }.not_to publish_event(MergeRequests::DraftStateChangeEvent)
- end
- end
-
context 'when removing through wip_event param' do
it 'removes Draft from the title' do
expect { update_merge_request({ wip_event: "ready" }) }
@@ -967,16 +957,6 @@ RSpec.describe MergeRequests::UpdateService, :mailer, feature_category: :code_re
end
end
- context 'when merge_when_checks_pass is disabled' do
- before do
- stub_feature_flags(merge_when_checks_pass: false)
- end
-
- it 'does not publish a DraftStateChangeEvent' do
- expect { update_merge_request(title: 'Draft: New title') }.not_to publish_event(MergeRequests::DraftStateChangeEvent)
- end
- end
-
it 'triggers GraphQL subscription mergeRequestMergeStatusUpdated' do
expect(GraphqlTriggers).to receive(:merge_request_merge_status_updated).with(merge_request)
diff --git a/spec/support/shared_examples/workers/auto_merge_from_event_shared_examples.rb b/spec/support/shared_examples/workers/auto_merge_from_event_shared_examples.rb
index 9db3ef43a85..9e76fc6971e 100644
--- a/spec/support/shared_examples/workers/auto_merge_from_event_shared_examples.rb
+++ b/spec/support/shared_examples/workers/auto_merge_from_event_shared_examples.rb
@@ -33,17 +33,5 @@ RSpec.shared_examples 'process auto merge from event worker' do
.not_to raise_exception
end
end
-
- context 'when feature flag "merge_when_checks_pass" is disabled' do
- before do
- stub_feature_flags(merge_when_checks_pass: false)
- end
-
- it "doesn't call AutoMergeService" do
- expect(AutoMergeService).not_to receive(:new)
-
- consume_event(subscriber: described_class, event: event)
- end
- end
end
end