summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-12-17 18:10:14 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-12-17 18:10:14 +0000
commitf3b791d5d5b0b058d2b717da1a54a63f3bba5adc (patch)
tree0f88def948be12834a60ca156502c304e0a10aa3
parentef73ee020e96f39a109a16c4c6b018d8ea7cabc1 (diff)
downloadgitlab-ce-f3b791d5d5b0b058d2b717da1a54a63f3bba5adc.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.rubocop_manual_todo.yml31
-rw-r--r--.rubocop_todo.yml221
-rw-r--r--app/controllers/concerns/issuable_actions.rb1
-rw-r--r--app/controllers/explore/projects_controller.rb7
-rw-r--r--app/graphql/mutations/boards/update.rb2
-rw-r--r--app/models/merge_request.rb12
-rw-r--r--app/services/concerns/update_repository_storage_methods.rb114
-rw-r--r--app/services/issuable/bulk_update_service.rb2
-rw-r--r--app/services/merge_requests/update_service.rb18
-rw-r--r--app/services/projects/update_repository_storage_service.rb120
-rw-r--r--app/services/snippets/update_repository_storage_service.rb21
-rw-r--r--changelogs/unreleased/chore-disable-admin-mode-in-lib.yml5
-rw-r--r--changelogs/unreleased/epic_boards_graphql_lists.yml5
-rw-r--r--changelogs/unreleased/lower-explore-pages.yml5
-rw-r--r--config/feature_flags/development/merge_orchestration_service.yml8
-rw-r--r--config/feature_flags/experiment/null_hypothesis.yml7
-rw-r--r--db/migrate/20201214184020_add_epic_board_list.rb33
-rw-r--r--db/schema_migrations/202012141840201
-rw-r--r--db/structure.sql37
-rw-r--r--doc/api/graphql/reference/gitlab_schema.graphql165
-rw-r--r--doc/api/graphql/reference/gitlab_schema.json432
-rw-r--r--doc/api/graphql/reference/index.md17
-rw-r--r--doc/ci/examples/authenticating-with-hashicorp-vault/index.md1
-rw-r--r--doc/development/documentation/styleguide/index.md2
-rw-r--r--doc/development/iterating_tables_in_batches.md25
-rw-r--r--doc/development/product_analytics/usage_ping.md3
-rw-r--r--doc/user/application_security/dependency_scanning/index.md5
-rw-r--r--lib/feature/shared.rb2
-rw-r--r--lib/gitlab/experimentation/experiment.rb4
-rw-r--r--lib/gitlab/quick_actions/merge_request_actions.rb40
-rw-r--r--locale/gitlab.pot14
-rw-r--r--spec/controllers/explore/projects_controller_spec.rb2
-rw-r--r--spec/finders/ci/daily_build_group_report_results_finder_spec.rb6
-rw-r--r--spec/frontend/issue_show/components/app_spec.js7
-rw-r--r--spec/frontend/sentry_error_stack_trace/components/sentry_error_stack_trace_spec.js5
-rw-r--r--spec/frontend_integration/ide/helpers/ide_helper.js4
-rw-r--r--spec/frontend_integration/ide/user_opens_file_spec.js4
-rw-r--r--spec/frontend_integration/test_helpers/setup/index.js1
-rw-r--r--spec/frontend_integration/test_helpers/setup/setup_testing_library.js3
-rw-r--r--spec/lib/banzai/filter/reference_redactor_filter_spec.rb31
-rw-r--r--spec/lib/constraints/admin_constrainer_spec.rb2
-rw-r--r--spec/lib/gitlab/auth/current_user_mode_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/AWS/deploy_ecs_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/Jobs/build_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/Jobs/code_quality_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/Jobs/test_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/Terraform/base_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/Verify/load_performance_testing_gitlab_ci_yaml_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/templates/flutter_gitlab_ci_yaml_spec.rb3
-rw-r--r--spec/lib/gitlab/ci/templates/npm_spec.rb3
-rw-r--r--spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb3
-rw-r--r--spec/lib/gitlab/cycle_analytics/base_event_fetcher_spec.rb2
-rw-r--r--spec/lib/gitlab/cycle_analytics/events_spec.rb2
-rw-r--r--spec/lib/gitlab/git_access_snippet_spec.rb20
-rw-r--r--spec/lib/gitlab/git_access_spec.rb56
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml1
-rw-r--r--spec/lib/gitlab/search_results_spec.rb39
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/admin_mode/client_spec.rb2
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/admin_mode/server_spec.rb2
-rw-r--r--spec/lib/gitlab/slash_commands/presenters/issue_move_spec.rb9
-rw-r--r--spec/lib/gitlab/user_access_spec.rb32
-rw-r--r--spec/lib/gitlab/visibility_level_spec.rb24
-rw-r--r--spec/models/merge_request_spec.rb106
-rw-r--r--spec/services/issuable/bulk_update_service_spec.rb51
-rw-r--r--spec/services/merge_requests/update_service_spec.rb8
-rw-r--r--spec/services/snippets/update_repository_storage_service_spec.rb137
-rw-r--r--spec/spec_helper.rb3
-rw-r--r--spec/support/helpers/stub_experiments.rb4
-rw-r--r--spec/support/shared_examples/lib/gitlab/project_search_results_shared_examples.rb19
71 files changed, 1424 insertions, 547 deletions
diff --git a/.rubocop_manual_todo.yml b/.rubocop_manual_todo.yml
index 2ffbef850d0..9adbd2cc828 100644
--- a/.rubocop_manual_todo.yml
+++ b/.rubocop_manual_todo.yml
@@ -1,3 +1,15 @@
+---
+# This file is not meant to store permanent exclusions.
+# - for permanent lists, place them in the .rubocop.yml.
+# - for short (less than 15 lines line) temporary lists, place them in the .rubocop_todo.yml file (run auto-generation).
+#
+# Purpose of this file:
+# - show long exclusion lists that are hidden in generic auto-generation of .rubocop_todo.yml.
+# - provide an 'in-flight' list of exclusions being worked on when qualifying as a long list
+# as mentioned above.
+# - guidelines for use found in
+# https://docs.gitlab.com/ee/development/contributing/style_guides.html#resolving-rubocop-exceptions.
+
FactoryBot/InlineAssociation:
Exclude:
- 'ee/spec/factories/analytics/cycle_analytics/group_stages.rb'
@@ -17,25 +29,6 @@ FactoryBot/InlineAssociation:
- 'spec/factories/uploads.rb'
- 'spec/factories/wiki_pages.rb'
-Graphql/IDType:
- Exclude:
- - 'ee/app/graphql/ee/mutations/issues/update.rb'
- - 'app/graphql/mutations/boards/issues/issue_move_list.rb'
- - 'app/graphql/resolvers/design_management/design_at_version_resolver.rb'
- - 'app/graphql/resolvers/design_management/design_resolver.rb'
- - 'app/graphql/resolvers/design_management/designs_resolver.rb'
- - 'app/graphql/resolvers/design_management/version/design_at_version_resolver.rb'
- - 'app/graphql/resolvers/design_management/version_in_collection_resolver.rb'
- - 'app/graphql/resolvers/design_management/version_resolver.rb'
- - 'app/graphql/resolvers/design_management/versions_resolver.rb'
- - 'app/graphql/resolvers/error_tracking/sentry_detailed_error_resolver.rb'
- - 'app/graphql/resolvers/error_tracking/sentry_error_stack_trace_resolver.rb'
- - 'app/graphql/resolvers/user_merge_requests_resolver.rb'
-
-Gitlab/PolicyRuleBoolean:
- Exclude:
- - 'ee/app/policies/ee/identity_provider_policy.rb'
-
Rails/SaveBang:
Exclude:
- 'ee/spec/controllers/projects/merge_requests_controller_spec.rb'
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index 293c8fccf33..6bf120b8fb8 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -1,49 +1,68 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
-# on 2020-10-29 17:35:37 UTC using RuboCop version 0.89.1.
+# on 2020-12-14 18:35:57 UTC using RuboCop version 0.89.1.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.
-# Offense count: 310
+# Offense count: 313
# Cop supports --auto-correct.
Capybara/CurrentPathExpectation:
Enabled: false
-# Offense count: 210
+# Offense count: 216
Capybara/VisibilityMatcher:
Enabled: false
-# Offense count: 1903
+# Offense count: 1
+Gitlab/PolicyRuleBoolean:
+ Exclude:
+ - 'ee/app/policies/ee/identity_provider_policy.rb'
+
+# Offense count: 5
+Graphql/IDType:
+ Exclude:
+ - 'app/graphql/mutations/boards/issues/issue_move_list.rb'
+
+# Offense count: 5
+Graphql/ResolverType:
+ Exclude:
+ - 'app/graphql/resolvers/base_resolver.rb'
+ - 'app/graphql/resolvers/ci/jobs_resolver.rb'
+ - 'app/graphql/resolvers/ci/pipeline_stages_resolver.rb'
+ - 'app/graphql/resolvers/users/group_count_resolver.rb'
+ - 'ee/app/graphql/resolvers/vulnerabilities_base_resolver.rb'
+
+# Offense count: 2002
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, IndentationWidth.
# SupportedStyles: with_first_argument, with_fixed_indentation
Layout/ArgumentAlignment:
Enabled: false
-# Offense count: 49
+# Offense count: 50
# Cop supports --auto-correct.
# Configuration parameters: AllowAliasSyntax, AllowedMethods.
# AllowedMethods: alias_method, public, protected, private
Layout/EmptyLinesAroundAttributeAccessor:
Enabled: false
-# Offense count: 610
+# Offense count: 694
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, IndentationWidth.
# SupportedStyles: special_inside_parentheses, consistent, align_brackets
Layout/FirstArrayElementIndentation:
Enabled: false
-# Offense count: 1535
+# Offense count: 1621
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, IndentationWidth.
# SupportedStyles: special_inside_parentheses, consistent, align_braces
Layout/FirstHashElementIndentation:
Enabled: false
-# Offense count: 2754
+# Offense count: 2979
# Cop supports --auto-correct.
# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
# SupportedHashRocketStyles: key, separator, table
@@ -52,14 +71,14 @@ Layout/FirstHashElementIndentation:
Layout/HashAlignment:
Enabled: false
-# Offense count: 64
+# Offense count: 72
# Cop supports --auto-correct.
# Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
# URISchemes: http, https
Layout/LineLength:
Max: 1313
-# Offense count: 118
+# Offense count: 162
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, IndentationWidth.
# SupportedStyles: aligned, indented
@@ -71,14 +90,14 @@ Layout/MultilineOperationIndentation:
Layout/SpaceAroundMethodCallOperator:
Enabled: false
-# Offense count: 790
+# Offense count: 737
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: require_no_space, require_space
Layout/SpaceInLambdaLiteral:
Enabled: false
-# Offense count: 1110
+# Offense count: 1160
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces, SpaceBeforeBlockParameters.
# SupportedStyles: space, no_space
@@ -86,14 +105,14 @@ Layout/SpaceInLambdaLiteral:
Layout/SpaceInsideBlockBraces:
Enabled: false
-# Offense count: 501
+# Offense count: 539
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: space, no_space
Layout/SpaceInsideParens:
Enabled: false
-# Offense count: 18
+# Offense count: 19
Lint/BinaryOperatorWithIdenticalOperands:
Exclude:
- 'app/finders/concerns/time_frame_filter.rb'
@@ -118,19 +137,13 @@ Lint/DeprecatedOpenSSLConstant:
- 'ee/lib/gitlab/geo/oauth/logout_state.rb'
- 'lib/gitlab/conan_token.rb'
- 'lib/gitlab/gitaly_client.rb'
- - 'lib/gitlab/kubernetes/helm/certificate.rb'
- 'lib/gitlab/kubernetes/helm/v2/certificate.rb'
- 'spec/lib/gitlab/conan_token_spec.rb'
- 'spec/services/pages_domains/obtain_lets_encrypt_certificate_service_spec.rb'
- 'spec/support/helpers/smime_helper.rb'
- 'spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb'
-# Offense count: 1
-Lint/FloatComparison:
- Exclude:
- - 'ee/app/models/ee/namespace.rb'
-
-# Offense count: 157
+# Offense count: 183
# Configuration parameters: MaximumRangeSize.
Lint/MissingCopEnableDirective:
Enabled: false
@@ -159,7 +172,7 @@ Lint/NonDeterministicRequireOrder:
Exclude:
- 'rubocop/rubocop.rb'
-# Offense count: 118
+# Offense count: 135
# Cop supports --auto-correct.
Lint/RedundantCopDisableDirective:
Enabled: false
@@ -187,17 +200,17 @@ Lint/UnreachableLoop:
Exclude:
- 'qa/qa/runtime/feature.rb'
-# Offense count: 5
+# Offense count: 7
# Configuration parameters: IgnoredMethods.
Metrics/AbcSize:
Max: 59
-# Offense count: 13
+# Offense count: 15
# Configuration parameters: IgnoredMethods.
Metrics/CyclomaticComplexity:
Max: 25
-# Offense count: 13
+# Offense count: 14
# Configuration parameters: IgnoredMethods.
Metrics/PerceivedComplexity:
Max: 25
@@ -208,7 +221,7 @@ Migration/DepartmentName:
Exclude:
- 'app/models/commit.rb'
-# Offense count: 171
+# Offense count: 181
# Configuration parameters: ExpectMatchingDefinition, CheckDefinitionPathHierarchy, Regex, IgnoreExecutableScripts, AllowedAcronyms.
# AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS
Naming/FileName:
@@ -225,7 +238,7 @@ Naming/HeredocDelimiterCase:
- 'spec/support/helpers/repo_helpers.rb'
- 'spec/support/helpers/seed_repo.rb'
-# Offense count: 263
+# Offense count: 303
# Configuration parameters: ForbiddenDelimiters.
# ForbiddenDelimiters: (?-mix:(^|\s)(EO[A-Z]{1}|END)(\s|$))
Naming/HeredocDelimiterNaming:
@@ -239,7 +252,7 @@ Naming/MethodParameterName:
- 'lib/gitlab/diff/inline_diff.rb'
- 'spec/support/helpers/key_generator_helper.rb'
-# Offense count: 191
+# Offense count: 203
# Cop supports --auto-correct.
# Configuration parameters: PreferredName.
Naming/RescuedExceptionsVariableName:
@@ -256,7 +269,7 @@ Performance/AncestorsInclude:
Performance/CollectionLiteralInLoop:
Enabled: false
-# Offense count: 19
+# Offense count: 18
# Cop supports --auto-correct.
Performance/Count:
Exclude:
@@ -267,10 +280,9 @@ Performance/Count:
- 'spec/lib/gitlab/conflict/file_spec.rb'
- 'spec/lib/gitlab/git/tree_spec.rb'
- 'spec/models/ci/build_spec.rb'
- - 'spec/support/matchers/exceed_query_limit.rb'
- 'spec/support_specs/helpers/active_record/query_recorder_spec.rb'
-# Offense count: 15
+# Offense count: 14
# Cop supports --auto-correct.
# Configuration parameters: SafeMultiline.
Performance/DeletePrefix:
@@ -283,14 +295,13 @@ Performance/DeletePrefix:
- 'lib/gitlab/gfm/uploads_rewriter.rb'
- 'lib/gitlab/git/ref.rb'
- 'lib/gitlab/project_template.rb'
- - 'lib/gitlab/repo_path.rb'
- 'lib/gitlab/setup_helper.rb'
- 'lib/gitlab/time_tracking_formatter.rb'
- 'spec/controllers/projects/artifacts_controller_spec.rb'
- 'spec/lib/gitlab/gfm/uploads_rewriter_spec.rb'
- 'spec/support/helpers/test_env.rb'
-# Offense count: 6
+# Offense count: 5
# Cop supports --auto-correct.
# Configuration parameters: SafeMultiline.
Performance/DeleteSuffix:
@@ -299,7 +310,6 @@ Performance/DeleteSuffix:
- 'app/workers/concerns/application_worker.rb'
- 'ee/app/models/geo/upload_registry.rb'
- 'ee/app/workers/geo/file_download_dispatch_worker/attachment_job_finder.rb'
- - 'lib/gitlab/repo_path.rb'
- 'lib/sentry/client/issue.rb'
# Offense count: 13
@@ -313,7 +323,7 @@ Performance/Detect:
- 'spec/lib/gitlab/import_export/project/tree_restorer_spec.rb'
- 'spec/models/event_spec.rb'
-# Offense count: 19
+# Offense count: 18
# Cop supports --auto-correct.
# Configuration parameters: AutoCorrect.
Performance/StringInclude:
@@ -330,7 +340,6 @@ Performance/StringInclude:
- 'qa/qa/ee/page/merge_request/show.rb'
- 'qa/qa/specs/runner.rb'
- 'spec/features/projects/jobs_spec.rb'
- - 'spec/lib/gitlab/import_export/project/tree_restorer_spec.rb'
- 'spec/spec_helper.rb'
- 'spec/support_specs/helpers/active_record/query_recorder_spec.rb'
@@ -346,7 +355,7 @@ Performance/Sum:
- 'lib/gitlab/sherlock/transaction.rb'
- 'lib/gitlab/usage_data.rb'
-# Offense count: 13879
+# Offense count: 14469
# Configuration parameters: Prefixes.
# Prefixes: when, with, without
RSpec/ContextWording:
@@ -359,65 +368,50 @@ RSpec/EmptyExampleGroup:
- 'ee/spec/services/personal_access_tokens/revoke_invalid_tokens_spec.rb'
- 'spec/services/projects/prometheus/alerts/notify_service_spec.rb'
-# Offense count: 1310
+# Offense count: 1355
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: method_call, block
RSpec/ExpectChange:
Enabled: false
-RSpec/ExpectGitlabTracking:
- Exclude:
- - 'ee/spec/requests/api/visual_review_discussions_spec.rb'
- - 'ee/spec/services/epics/issue_promote_service_spec.rb'
- - 'spec/controllers/groups/registry/repositories_controller_spec.rb'
- - 'spec/controllers/projects/registry/repositories_controller_spec.rb'
- - 'spec/controllers/projects/registry/tags_controller_spec.rb'
- - 'spec/controllers/projects/settings/operations_controller_spec.rb'
- - 'spec/lib/api/helpers_spec.rb'
- - 'spec/requests/api/project_container_repositories_spec.rb'
- - 'spec/support/shared_examples/controllers/trackable_shared_examples.rb'
- - 'spec/support/shared_examples/requests/api/discussions_shared_examples.rb'
- - 'spec/support/shared_examples/requests/api/packages_shared_examples.rb'
- - 'spec/support/shared_examples/requests/api/tracking_shared_examples.rb'
-
-# Offense count: 888
+# Offense count: 903
RSpec/ExpectInHook:
Enabled: false
-# Offense count: 15945
+# Offense count: 16472
# Configuration parameters: AllowSubject.
RSpec/MultipleMemoizedHelpers:
Max: 40
-# Offense count: 2297
+# Offense count: 2344
# Cop supports --auto-correct.
# Configuration parameters: Strict, EnforcedStyle, AllowedExplicitMatchers.
# SupportedStyles: inflected, explicit
RSpec/PredicateMatcher:
Enabled: false
-# Offense count: 98
+# Offense count: 112
RSpec/RepeatedExampleGroupBody:
Enabled: false
-# Offense count: 213
+# Offense count: 219
RSpec/RepeatedExampleGroupDescription:
Enabled: false
-# Offense count: 636
+# Offense count: 655
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: and_return, block
RSpec/ReturnFromStub:
Enabled: false
-# Offense count: 574
+# Offense count: 587
# Cop supports --auto-correct.
RSpec/ScatteredLet:
Enabled: false
-# Offense count: 4
+# Offense count: 6
RSpec/ScatteredSetup:
Exclude:
- 'spec/requests/api/jobs_spec.rb'
@@ -429,7 +423,7 @@ RSpec/VariableDefinition:
Exclude:
- 'spec/initializers/mail_encoding_patch_spec.rb'
-# Offense count: 25
+# Offense count: 24
# Configuration parameters: EnforcedStyle, IgnoredPatterns.
# SupportedStyles: snake_case, camelCase
RSpec/VariableName:
@@ -437,13 +431,12 @@ RSpec/VariableName:
- 'spec/features/projects/import_export/import_file_spec.rb'
- 'spec/features/task_lists_spec.rb'
- 'spec/initializers/mail_encoding_patch_spec.rb'
- - 'spec/lib/gitlab/experimentation_spec.rb'
- 'spec/models/board_spec.rb'
- 'spec/support/shared_contexts/url_shared_context.rb'
- 'spec/support/shared_examples/requests/api/graphql/group_and_project_boards_query_shared_examples.rb'
- 'spec/support/shared_examples/services/boards/boards_list_service_shared_examples.rb'
-# Offense count: 27
+# Offense count: 25
# Cop supports --auto-correct.
# Configuration parameters: Include.
# Include: app/models/**/*.rb
@@ -472,25 +465,25 @@ Rails/BelongsTo:
- 'app/models/deployment.rb'
- 'app/models/environment.rb'
-# Offense count: 84
+# Offense count: 88
# Configuration parameters: Database, Include.
# SupportedDatabases: mysql, postgresql
# Include: db/migrate/*.rb
Rails/BulkChangeTable:
Enabled: false
-# Offense count: 151
+# Offense count: 153
# Cop supports --auto-correct.
Rails/ContentTag:
Enabled: false
-# Offense count: 270
+# Offense count: 292
# Configuration parameters: Include.
# Include: db/migrate/*.rb
Rails/CreateTableWithTimestamps:
Enabled: false
-# Offense count: 323
+# Offense count: 343
# Configuration parameters: EnforcedStyle.
# SupportedStyles: slashes, arguments
Rails/FilePath:
@@ -512,13 +505,13 @@ Rails/FindById:
- 'spec/finders/concerns/finder_methods_spec.rb'
- 'spec/finders/concerns/finder_with_cross_project_access_spec.rb'
-# Offense count: 329
+# Offense count: 343
# Configuration parameters: Include.
# Include: app/models/**/*.rb
Rails/HasManyOrHasOneDependent:
Enabled: false
-# Offense count: 507
+# Offense count: 538
# Configuration parameters: Include.
# Include: app/helpers/**/*.rb
Rails/HelperInstanceVariable:
@@ -542,7 +535,7 @@ Rails/IndexBy:
- 'lib/gitlab/database/count/reltuples_count_strategy.rb'
- 'lib/gitlab/language_detection.rb'
-# Offense count: 44
+# Offense count: 45
# Cop supports --auto-correct.
Rails/IndexWith:
Enabled: false
@@ -552,7 +545,7 @@ Rails/Inquiry:
Exclude:
- 'spec/helpers/labels_helper_spec.rb'
-# Offense count: 112
+# Offense count: 115
# Configuration parameters: Include.
# Include: app/models/**/*.rb
Rails/InverseOf:
@@ -580,33 +573,34 @@ Rails/MailerName:
Exclude:
- 'app/mailers/notify.rb'
-# Offense count: 48
+# Offense count: 49
# Cop supports --auto-correct.
Rails/NegateInclude:
Enabled: false
-# Offense count: 41
+# Offense count: 42
# Cop supports --auto-correct.
Rails/Pick:
Enabled: false
-# Offense count: 113
+# Offense count: 119
# Cop supports --auto-correct.
Rails/Pluck:
Enabled: false
-# Offense count: 38
+# Offense count: 39
# Cop supports --auto-correct.
# Configuration parameters: Include.
# Include: **/Rakefile, **/*.rake
Rails/RakeEnvironment:
Enabled: false
-# Offense count: 52
+# Offense count: 56
# Cop supports --auto-correct.
Rails/RedundantForeignKey:
Enabled: false
+# Offense count: 1
Rails/RenderInline:
Exclude:
- 'ee/app/controllers/sitemap_controller.rb'
@@ -621,18 +615,18 @@ Rails/ShortI18n:
- 'app/uploaders/content_type_whitelist.rb'
- 'spec/views/shared/runners/show.html.haml_spec.rb'
-# Offense count: 1043
+# Offense count: 1064
# Configuration parameters: ForbiddenMethods, AllowedMethods.
# ForbiddenMethods: decrement!, decrement_counter, increment!, increment_counter, insert, insert!, insert_all, insert_all!, toggle!, touch, touch_all, update_all, update_attribute, update_column, update_columns, update_counters, upsert, upsert_all
Rails/SkipsModelValidations:
Enabled: false
-# Offense count: 202
+# Offense count: 245
# Cop supports --auto-correct.
Rails/SquishedSQLHeredocs:
Enabled: false
-# Offense count: 37
+# Offense count: 38
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: exists, where
@@ -654,7 +648,7 @@ Security/YAMLLoad:
- 'spec/initializers/secret_token_spec.rb'
- 'spec/lib/gitlab/prometheus/additional_metrics_parser_spec.rb'
-# Offense count: 240
+# Offense count: 247
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: separated, grouped
@@ -679,7 +673,7 @@ Style/ArrayCoercion:
- 'ee/lib/ee/banzai/pipeline/gfm_pipeline.rb'
- 'spec/support/helpers/lfs_http_helpers.rb'
-# Offense count: 176
+# Offense count: 184
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: percent_q, bare_percent
@@ -693,7 +687,7 @@ Style/BisectedAttrAccessor:
- 'lib/system_check/base_check.rb'
- 'qa/qa/resource/api_fabricator.rb'
-# Offense count: 37
+# Offense count: 36
# Cop supports --auto-correct.
Style/CaseLikeIf:
Enabled: false
@@ -716,14 +710,14 @@ Style/EachWithObject:
- 'lib/gitlab/i18n/po_linter.rb'
- 'lib/gitlab/import_export/members_mapper.rb'
-# Offense count: 53
+# Offense count: 54
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: empty, nil, both
Style/EmptyElse:
Enabled: false
-# Offense count: 193
+# Offense count: 198
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: compact, expanded
@@ -737,51 +731,51 @@ Style/ExpandPathArguments:
- 'cable/config.ru'
- 'config.ru'
-# Offense count: 118
+# Offense count: 114
# Cop supports --auto-correct.
Style/ExplicitBlockArgument:
Enabled: false
-# Offense count: 521
+# Offense count: 542
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: format, sprintf, percent
Style/FormatString:
Enabled: false
-# Offense count: 48
+# Offense count: 59
# Cop supports --auto-correct.
Style/GlobalStdStream:
Enabled: false
-# Offense count: 835
+# Offense count: 857
# Configuration parameters: MinBodyLength.
Style/GuardClause:
Enabled: false
-# Offense count: 93
+# Offense count: 92
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: braces, no_braces
Style/HashAsLastArrayItem:
Enabled: false
-# Offense count: 55
+# Offense count: 60
# Cop supports --auto-correct.
Style/HashEachMethods:
Enabled: false
-# Offense count: 30
+# Offense count: 34
# Configuration parameters: AllowIfModifier.
Style/IfInsideElse:
Enabled: false
-# Offense count: 1798
+# Offense count: 1856
# Cop supports --auto-correct.
Style/IfUnlessModifier:
Enabled: false
-# Offense count: 447
+# Offense count: 439
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: line_count_dependent, lambda, literal
@@ -792,39 +786,39 @@ Style/Lambda:
Style/MissingRespondToMissing:
Enabled: false
-# Offense count: 32
+# Offense count: 36
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, MinBodyLength.
# SupportedStyles: skip_modifier_ifs, always
Style/Next:
Enabled: false
-# Offense count: 95
+# Offense count: 98
# Cop supports --auto-correct.
# Configuration parameters: EnforcedOctalStyle.
# SupportedOctalStyles: zero_with_o, zero_only
Style/NumericLiteralPrefix:
Enabled: false
-# Offense count: 132
+# Offense count: 136
# Cop supports --auto-correct.
Style/ParallelAssignment:
Enabled: false
-# Offense count: 2473
+# Offense count: 2557
# Cop supports --auto-correct.
# Configuration parameters: PreferredDelimiters.
Style/PercentLiteralDelimiters:
Enabled: false
-# Offense count: 246
+# Offense count: 251
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: compact, exploded
Style/RaiseArgs:
Enabled: false
-# Offense count: 66
+# Offense count: 68
# Cop supports --auto-correct.
Style/RedundantAssignment:
Enabled: false
@@ -846,22 +840,21 @@ Style/RedundantFetchBlock:
Style/RedundantFileExtensionInRequire:
Enabled: false
-# Offense count: 260
+# Offense count: 272
# Cop supports --auto-correct.
Style/RedundantFreeze:
Enabled: false
-# Offense count: 167
+# Offense count: 179
# Cop supports --auto-correct.
Style/RedundantInterpolation:
Enabled: false
-# Offense count: 11
+# Offense count: 9
# Cop supports --auto-correct.
Style/RedundantRegexpCharacterClass:
Exclude:
- 'app/models/concerns/taskable.rb'
- - 'ee/lib/ee/gitlab/path_regex.rb'
- 'lib/gitlab/authorized_keys.rb'
- 'lib/gitlab/fogbugz_import/repository.rb'
- 'lib/gitlab/prometheus/internal.rb'
@@ -870,17 +863,17 @@ Style/RedundantRegexpCharacterClass:
- 'spec/features/merge_request/user_views_open_merge_request_spec.rb'
- 'spec/tasks/gitlab/usage_data_rake_spec.rb'
-# Offense count: 250
+# Offense count: 270
# Cop supports --auto-correct.
Style/RedundantRegexpEscape:
Enabled: false
-# Offense count: 868
+# Offense count: 914
# Cop supports --auto-correct.
Style/RedundantSelf:
Enabled: false
-# Offense count: 179
+# Offense count: 190
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, AllowInnerSlashes.
# SupportedStyles: slashes, percent_r, mixed
@@ -892,43 +885,43 @@ Style/RegexpLiteral:
Style/RescueModifier:
Enabled: false
-# Offense count: 329
+# Offense count: 338
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: implicit, explicit
Style/RescueStandardError:
Enabled: false
-# Offense count: 104
+# Offense count: 110
# Cop supports --auto-correct.
Style/SingleArgumentDig:
Enabled: false
-# Offense count: 47
+# Offense count: 46
# Cop supports --auto-correct.
Style/SlicingWithRange:
Enabled: false
-# Offense count: 109
+# Offense count: 120
# Cop supports --auto-correct.
# Configuration parameters: .
# SupportedStyles: use_perl_names, use_english_names
Style/SpecialGlobalVars:
EnforcedStyle: use_perl_names
-# Offense count: 516
+# Offense count: 532
# Cop supports --auto-correct.
Style/StringConcatenation:
Enabled: false
-# Offense count: 103
+# Offense count: 104
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: single_quotes, double_quotes
Style/StringLiteralsInInterpolation:
Enabled: false
-# Offense count: 276
+# Offense count: 296
# Cop supports --auto-correct.
# Configuration parameters: IgnoredMethods.
# IgnoredMethods: respond_to, define_method
diff --git a/app/controllers/concerns/issuable_actions.rb b/app/controllers/concerns/issuable_actions.rb
index 3b46a547d47..57d4203ad43 100644
--- a/app/controllers/concerns/issuable_actions.rb
+++ b/app/controllers/concerns/issuable_actions.rb
@@ -217,6 +217,7 @@ module IssuableActions
:issuable_ids,
:assignee_id,
:milestone_id,
+ :sprint_id,
:state_event,
:subscription_event,
assignee_ids: [],
diff --git a/app/controllers/explore/projects_controller.rb b/app/controllers/explore/projects_controller.rb
index d210d0f66fd..1fd3cfd11f9 100644
--- a/app/controllers/explore/projects_controller.rb
+++ b/app/controllers/explore/projects_controller.rb
@@ -9,13 +9,16 @@ class Explore::ProjectsController < Explore::ApplicationController
include SortingPreference
MIN_SEARCH_LENGTH = 3
+ PAGE_LIMIT = 50
before_action :set_non_archived_param
before_action :set_sorting
- # Limit taken from https://gitlab.com/gitlab-org/gitlab/issues/38357
+ # For background information on the limit, see:
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/38357
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/262682
before_action only: [:index, :trending, :starred] do
- limit_pages(200)
+ limit_pages(PAGE_LIMIT)
end
rescue_from PageOutOfBoundsError, with: :page_out_of_bounds
diff --git a/app/graphql/mutations/boards/update.rb b/app/graphql/mutations/boards/update.rb
index 5cb434e41fd..b4f8179829e 100644
--- a/app/graphql/mutations/boards/update.rb
+++ b/app/graphql/mutations/boards/update.rb
@@ -30,6 +30,8 @@ module Mutations
}
end
+ private
+
def find_object(id:)
# TODO: remove this line when the compatibility layer is removed
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 043f07cf9f3..929e95b847e 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -1639,18 +1639,6 @@ class MergeRequest < ApplicationRecord
!has_commits?
end
- def mergeable_with_quick_action?(current_user, autocomplete_precheck: false, last_diff_sha: nil)
- return false unless can_be_merged_by?(current_user)
-
- return true if autocomplete_precheck
-
- return false unless mergeable?(skip_ci_check: true)
- return false if actual_head_pipeline && !(actual_head_pipeline.success? || actual_head_pipeline.active?)
- return false if last_diff_sha != diff_head_sha
-
- true
- end
-
def pipeline_coverage_delta
if base_pipeline&.coverage && head_pipeline&.coverage
'%.2f' % (head_pipeline.coverage.to_f - base_pipeline.coverage.to_f)
diff --git a/app/services/concerns/update_repository_storage_methods.rb b/app/services/concerns/update_repository_storage_methods.rb
new file mode 100644
index 00000000000..c3a55e9379e
--- /dev/null
+++ b/app/services/concerns/update_repository_storage_methods.rb
@@ -0,0 +1,114 @@
+# frozen_string_literal: true
+
+module UpdateRepositoryStorageMethods
+ Error = Class.new(StandardError)
+ SameFilesystemError = Class.new(Error)
+
+ attr_reader :repository_storage_move
+ delegate :container, :source_storage_name, :destination_storage_name, to: :repository_storage_move
+
+ def initialize(repository_storage_move)
+ @repository_storage_move = repository_storage_move
+ end
+
+ def execute
+ repository_storage_move.with_lock do
+ return ServiceResponse.success unless repository_storage_move.scheduled? # rubocop:disable Cop/AvoidReturnFromBlocks
+
+ repository_storage_move.start!
+ end
+
+ raise SameFilesystemError if same_filesystem?(source_storage_name, destination_storage_name)
+
+ mirror_repositories
+
+ repository_storage_move.transaction do
+ repository_storage_move.finish_replication!
+
+ track_repository(destination_storage_name)
+ end
+
+ remove_old_paths
+ enqueue_housekeeping
+
+ repository_storage_move.finish_cleanup!
+
+ ServiceResponse.success
+ rescue StandardError => e
+ repository_storage_move.do_fail!
+
+ Gitlab::ErrorTracking.track_exception(e, container_klass: container.class.to_s, container_path: container.full_path)
+
+ ServiceResponse.error(
+ message: s_("UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}") % { container_full_path: container.full_path, message: e.message }
+ )
+ end
+
+ private
+
+ def track_repository(destination_shard)
+ raise NotImplementedError
+ end
+
+ def mirror_repositories
+ raise NotImplementedError
+ end
+
+ def mirror_repository(type:)
+ unless wait_for_pushes(type)
+ raise Error, s_('UpdateRepositoryStorage|Timeout waiting for %{type} repository pushes') % { type: type.name }
+ end
+
+ repository = type.repository_for(container)
+ full_path = repository.full_path
+ raw_repository = repository.raw
+ checksum = repository.checksum
+
+ # Initialize a git repository on the target path
+ new_repository = Gitlab::Git::Repository.new(
+ destination_storage_name,
+ raw_repository.relative_path,
+ raw_repository.gl_repository,
+ full_path
+ )
+
+ new_repository.replicate(raw_repository)
+ new_checksum = new_repository.checksum
+
+ if checksum != new_checksum
+ raise Error, s_('UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}') % { type: type.name, old: checksum, new: new_checksum }
+ end
+ end
+
+ def same_filesystem?(old_storage, new_storage)
+ Gitlab::GitalyClient.filesystem_id(old_storage) == Gitlab::GitalyClient.filesystem_id(new_storage)
+ end
+
+ def remove_old_paths
+ if container.repository_exists?
+ Gitlab::Git::Repository.new(
+ source_storage_name,
+ "#{container.disk_path}.git",
+ nil,
+ nil
+ ).remove
+ end
+ end
+
+ def enqueue_housekeeping
+ # no-op
+ end
+
+ def wait_for_pushes(type)
+ reference_counter = container.reference_counter(type: type)
+
+ # Try for 30 seconds, polling every 10
+ 3.times do
+ return true if reference_counter.value == 0
+
+ sleep 10
+ end
+
+ false
+ end
+end
diff --git a/app/services/issuable/bulk_update_service.rb b/app/services/issuable/bulk_update_service.rb
index 79be771b3fb..d3d543edcd7 100644
--- a/app/services/issuable/bulk_update_service.rb
+++ b/app/services/issuable/bulk_update_service.rb
@@ -34,6 +34,8 @@ module Issuable
def permitted_attrs(type)
attrs = %i(state_event milestone_id add_label_ids remove_label_ids subscription_event)
+ attrs.push(:sprint_id) if type == 'issue'
+
if type == 'issue' || type == 'merge_request'
attrs.push(:assignee_ids)
else
diff --git a/app/services/merge_requests/update_service.rb b/app/services/merge_requests/update_service.rb
index bff7a43dd7b..826a48fdcf9 100644
--- a/app/services/merge_requests/update_service.rb
+++ b/app/services/merge_requests/update_service.rb
@@ -132,21 +132,9 @@ module MergeRequests
def merge_from_quick_action(merge_request)
last_diff_sha = params.delete(:merge)
- if Feature.enabled?(:merge_orchestration_service, merge_request.project, default_enabled: true)
- MergeRequests::MergeOrchestrationService
- .new(project, current_user, { sha: last_diff_sha })
- .execute(merge_request)
- else
- return unless merge_request.mergeable_with_quick_action?(current_user, last_diff_sha: last_diff_sha)
-
- merge_request.update(merge_error: nil)
-
- if merge_request.head_pipeline_active?
- AutoMergeService.new(project, current_user, { sha: last_diff_sha }).execute(merge_request, AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS)
- else
- merge_request.merge_async(current_user.id, { sha: last_diff_sha })
- end
- end
+ MergeRequests::MergeOrchestrationService
+ .new(project, current_user, { sha: last_diff_sha })
+ .execute(merge_request)
end
override :quick_action_options
diff --git a/app/services/projects/update_repository_storage_service.rb b/app/services/projects/update_repository_storage_service.rb
index e0d2398bc66..5c55da1fb2e 100644
--- a/app/services/projects/update_repository_storage_service.rb
+++ b/app/services/projects/update_repository_storage_service.rb
@@ -2,59 +2,19 @@
module Projects
class UpdateRepositoryStorageService
- Error = Class.new(StandardError)
- SameFilesystemError = Class.new(Error)
+ include UpdateRepositoryStorageMethods
- attr_reader :repository_storage_move
- delegate :project, :source_storage_name, :destination_storage_name, to: :repository_storage_move
-
- def initialize(repository_storage_move)
- @repository_storage_move = repository_storage_move
- end
-
- def execute
- repository_storage_move.with_lock do
- return ServiceResponse.success unless repository_storage_move.scheduled? # rubocop:disable Cop/AvoidReturnFromBlocks
-
- repository_storage_move.start!
- end
-
- raise SameFilesystemError if same_filesystem?(source_storage_name, destination_storage_name)
-
- mirror_repositories
-
- repository_storage_move.transaction do
- repository_storage_move.finish_replication!
-
- project.leave_pool_repository
- project.track_project_repository
- end
-
- remove_old_paths
- enqueue_housekeeping
-
- repository_storage_move.finish_cleanup!
-
- ServiceResponse.success
-
- rescue StandardError => e
- repository_storage_move.do_fail!
-
- Gitlab::ErrorTracking.track_exception(e, project_path: project.full_path)
-
- ServiceResponse.error(
- message: s_("UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}") % { project_full_path: project.full_path, message: e.message }
- )
- end
+ delegate :project, to: :repository_storage_move
private
- def same_filesystem?(old_storage, new_storage)
- Gitlab::GitalyClient.filesystem_id(old_storage) == Gitlab::GitalyClient.filesystem_id(new_storage)
+ def track_repository(_destination_storage_name)
+ project.leave_pool_repository
+ project.track_project_repository
end
def mirror_repositories
- mirror_repository if project.repository_exists?
+ mirror_repository(type: Gitlab::GlRepository::PROJECT) if project.repository_exists?
if project.wiki.repository_exists?
mirror_repository(type: Gitlab::GlRepository::WIKI)
@@ -65,41 +25,21 @@ module Projects
end
end
- def mirror_repository(type: Gitlab::GlRepository::PROJECT)
- unless wait_for_pushes(type)
- raise Error, s_('UpdateRepositoryStorage|Timeout waiting for %{type} repository pushes') % { type: type.name }
- end
-
- repository = type.repository_for(project)
- full_path = repository.full_path
- raw_repository = repository.raw
- checksum = repository.checksum
-
- # Initialize a git repository on the target path
- new_repository = Gitlab::Git::Repository.new(
- destination_storage_name,
- raw_repository.relative_path,
- raw_repository.gl_repository,
- full_path
- )
-
- new_repository.replicate(raw_repository)
- new_checksum = new_repository.checksum
+ # The underlying FetchInternalRemote call uses a `git fetch` to move data
+ # to the new repository, which leaves it in a less-well-packed state,
+ # lacking bitmaps and commit graphs. Housekeeping will boost performance
+ # significantly.
+ def enqueue_housekeeping
+ return unless Gitlab::CurrentSettings.housekeeping_enabled?
+ return unless Feature.enabled?(:repack_after_shard_migration, project)
- if checksum != new_checksum
- raise Error, s_('UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}') % { type: type.name, old: checksum, new: new_checksum }
- end
+ Projects::HousekeepingService.new(project, :gc).execute
+ rescue Projects::HousekeepingService::LeaseTaken
+ # No action required
end
def remove_old_paths
- if project.repository_exists?
- Gitlab::Git::Repository.new(
- source_storage_name,
- "#{project.disk_path}.git",
- nil,
- nil
- ).remove
- end
+ super
if project.wiki.repository_exists?
Gitlab::Git::Repository.new(
@@ -119,31 +59,5 @@ module Projects
).remove
end
end
-
- # The underlying FetchInternalRemote call uses a `git fetch` to move data
- # to the new repository, which leaves it in a less-well-packed state,
- # lacking bitmaps and commit graphs. Housekeeping will boost performance
- # significantly.
- def enqueue_housekeeping
- return unless Gitlab::CurrentSettings.housekeeping_enabled?
- return unless Feature.enabled?(:repack_after_shard_migration, project)
-
- Projects::HousekeepingService.new(project, :gc).execute
- rescue Projects::HousekeepingService::LeaseTaken
- # No action required
- end
-
- def wait_for_pushes(type)
- reference_counter = project.reference_counter(type: type)
-
- # Try for 30 seconds, polling every 10
- 3.times do
- return true if reference_counter.value == 0
-
- sleep 10
- end
-
- false
- end
end
end
diff --git a/app/services/snippets/update_repository_storage_service.rb b/app/services/snippets/update_repository_storage_service.rb
new file mode 100644
index 00000000000..3addae3b3be
--- /dev/null
+++ b/app/services/snippets/update_repository_storage_service.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Snippets
+ class UpdateRepositoryStorageService
+ include UpdateRepositoryStorageMethods
+
+ delegate :snippet, to: :repository_storage_move
+
+ private
+
+ def track_repository(destination_storage_name)
+ snippet.track_snippet_repository(destination_storage_name)
+ end
+
+ def mirror_repositories
+ return unless snippet.repository_exists?
+
+ mirror_repository(type: Gitlab::GlRepository::SNIPPET)
+ end
+ end
+end
diff --git a/changelogs/unreleased/chore-disable-admin-mode-in-lib.yml b/changelogs/unreleased/chore-disable-admin-mode-in-lib.yml
new file mode 100644
index 00000000000..6c04146472d
--- /dev/null
+++ b/changelogs/unreleased/chore-disable-admin-mode-in-lib.yml
@@ -0,0 +1,5 @@
+---
+title: Disable auto admin mode for lib specs
+merge_request: 50056
+author: Diego Louzán
+type: other
diff --git a/changelogs/unreleased/epic_boards_graphql_lists.yml b/changelogs/unreleased/epic_boards_graphql_lists.yml
new file mode 100644
index 00000000000..47c0887f566
--- /dev/null
+++ b/changelogs/unreleased/epic_boards_graphql_lists.yml
@@ -0,0 +1,5 @@
+---
+title: Add epic board list table
+merge_request: 49728
+author:
+type: added
diff --git a/changelogs/unreleased/lower-explore-pages.yml b/changelogs/unreleased/lower-explore-pages.yml
new file mode 100644
index 00000000000..222ab9461d3
--- /dev/null
+++ b/changelogs/unreleased/lower-explore-pages.yml
@@ -0,0 +1,5 @@
+---
+title: Lower /explore page limit
+merge_request: 50233
+author:
+type: performance
diff --git a/config/feature_flags/development/merge_orchestration_service.yml b/config/feature_flags/development/merge_orchestration_service.yml
deleted file mode 100644
index 52de3b6e733..00000000000
--- a/config/feature_flags/development/merge_orchestration_service.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: merge_orchestration_service
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28532
-rollout_issue_url:
-milestone: '12.10'
-type: development
-group: group::continuous integration
-default_enabled: true
diff --git a/config/feature_flags/experiment/null_hypothesis.yml b/config/feature_flags/experiment/null_hypothesis.yml
new file mode 100644
index 00000000000..716b0711ef1
--- /dev/null
+++ b/config/feature_flags/experiment/null_hypothesis.yml
@@ -0,0 +1,7 @@
+---
+name: null_hypothesis
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45840
+rollout_issue_url:
+type: experiment
+group: group::adoption
+default_enabled: false
diff --git a/db/migrate/20201214184020_add_epic_board_list.rb b/db/migrate/20201214184020_add_epic_board_list.rb
new file mode 100644
index 00000000000..9c4e3280754
--- /dev/null
+++ b/db/migrate/20201214184020_add_epic_board_list.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+class AddEpicBoardList < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ unless table_exists?(:boards_epic_lists)
+ with_lock_retries do
+ create_table :boards_epic_lists do |t|
+ t.timestamps_with_timezone
+ t.references :epic_board, index: true, foreign_key: { to_table: :boards_epic_boards, on_delete: :cascade }, null: false
+ t.references :label, index: true, foreign_key: { on_delete: :cascade }
+ t.integer :position
+ t.integer :list_type, default: 1, limit: 2, null: false
+
+ t.index [:epic_board_id, :label_id], unique: true, where: 'list_type = 1', name: 'index_boards_epic_lists_on_epic_board_id_and_label_id'
+ end
+ end
+ end
+
+ add_check_constraint :boards_epic_lists, '(list_type <> 1) OR ("position" IS NOT NULL AND "position" >= 0)', 'boards_epic_lists_position_constraint'
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :boards_epic_lists
+ end
+ end
+end
diff --git a/db/schema_migrations/20201214184020 b/db/schema_migrations/20201214184020
new file mode 100644
index 00000000000..5cf5065b251
--- /dev/null
+++ b/db/schema_migrations/20201214184020
@@ -0,0 +1 @@
+adce3c714064991e93f8a587da3d5892c47dbc14963fa49638ebbbf8b5489359 \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 105b7701409..f9969d247b0 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -9909,6 +9909,26 @@ CREATE SEQUENCE boards_epic_boards_id_seq
ALTER SEQUENCE boards_epic_boards_id_seq OWNED BY boards_epic_boards.id;
+CREATE TABLE boards_epic_lists (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ epic_board_id bigint NOT NULL,
+ label_id bigint,
+ "position" integer,
+ list_type smallint DEFAULT 1 NOT NULL,
+ CONSTRAINT boards_epic_lists_position_constraint CHECK (((list_type <> 1) OR (("position" IS NOT NULL) AND ("position" >= 0))))
+);
+
+CREATE SEQUENCE boards_epic_lists_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE boards_epic_lists_id_seq OWNED BY boards_epic_lists.id;
+
CREATE TABLE boards_epic_user_preferences (
id bigint NOT NULL,
board_id bigint NOT NULL,
@@ -18130,6 +18150,8 @@ ALTER TABLE ONLY boards_epic_board_positions ALTER COLUMN id SET DEFAULT nextval
ALTER TABLE ONLY boards_epic_boards ALTER COLUMN id SET DEFAULT nextval('boards_epic_boards_id_seq'::regclass);
+ALTER TABLE ONLY boards_epic_lists ALTER COLUMN id SET DEFAULT nextval('boards_epic_lists_id_seq'::regclass);
+
ALTER TABLE ONLY boards_epic_user_preferences ALTER COLUMN id SET DEFAULT nextval('boards_epic_user_preferences_id_seq'::regclass);
ALTER TABLE ONLY broadcast_messages ALTER COLUMN id SET DEFAULT nextval('broadcast_messages_id_seq'::regclass);
@@ -19173,6 +19195,9 @@ ALTER TABLE ONLY boards_epic_board_positions
ALTER TABLE ONLY boards_epic_boards
ADD CONSTRAINT boards_epic_boards_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY boards_epic_lists
+ ADD CONSTRAINT boards_epic_lists_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY boards_epic_user_preferences
ADD CONSTRAINT boards_epic_user_preferences_pkey PRIMARY KEY (id);
@@ -20824,6 +20849,12 @@ CREATE INDEX index_boards_epic_board_positions_on_epic_id ON boards_epic_board_p
CREATE INDEX index_boards_epic_boards_on_group_id ON boards_epic_boards USING btree (group_id);
+CREATE INDEX index_boards_epic_lists_on_epic_board_id ON boards_epic_lists USING btree (epic_board_id);
+
+CREATE UNIQUE INDEX index_boards_epic_lists_on_epic_board_id_and_label_id ON boards_epic_lists USING btree (epic_board_id, label_id) WHERE (list_type = 1);
+
+CREATE INDEX index_boards_epic_lists_on_label_id ON boards_epic_lists USING btree (label_id);
+
CREATE INDEX index_boards_epic_user_preferences_on_board_id ON boards_epic_user_preferences USING btree (board_id);
CREATE UNIQUE INDEX index_boards_epic_user_preferences_on_board_user_epic_unique ON boards_epic_user_preferences USING btree (board_id, user_id, epic_id);
@@ -24029,6 +24060,9 @@ ALTER TABLE ONLY user_synced_attributes_metadata
ALTER TABLE ONLY project_authorizations
ADD CONSTRAINT fk_rails_0f84bb11f3 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY boards_epic_lists
+ ADD CONSTRAINT fk_rails_0f9c7f646f FOREIGN KEY (epic_board_id) REFERENCES boards_epic_boards(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY issue_email_participants
ADD CONSTRAINT fk_rails_0fdfd8b811 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
@@ -24134,6 +24168,9 @@ ALTER TABLE ONLY boards_epic_board_positions
ALTER TABLE ONLY geo_repository_created_events
ADD CONSTRAINT fk_rails_1f49e46a61 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY boards_epic_lists
+ ADD CONSTRAINT fk_rails_1fe6b54909 FOREIGN KEY (label_id) REFERENCES labels(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY approval_merge_request_rules_groups
ADD CONSTRAINT fk_rails_2020a7124a FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
diff --git a/doc/api/graphql/reference/gitlab_schema.graphql b/doc/api/graphql/reference/gitlab_schema.graphql
index d7ad70c808e..06a2d937297 100644
--- a/doc/api/graphql/reference/gitlab_schema.graphql
+++ b/doc/api/graphql/reference/gitlab_schema.graphql
@@ -2225,6 +2225,11 @@ Identifier of Boards::EpicBoard
"""
scalar BoardsEpicBoardID
+"""
+Identifier of Boards::EpicList
+"""
+scalar BoardsEpicListID
+
type Branch {
"""
Commit for the branch
@@ -3976,6 +3981,11 @@ Autogenerated input type of CreateBoard
"""
input CreateBoardInput {
"""
+ The ID of user to be assigned to the board.
+ """
+ assigneeId: UserID
+
+ """
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
@@ -3996,6 +4006,26 @@ input CreateBoardInput {
hideClosedList: Boolean
"""
+ The ID of iteration to be assigned to the board.
+ """
+ iterationId: IterationID
+
+ """
+ The IDs of labels to be added to the board.
+ """
+ labelIds: [LabelID!]
+
+ """
+ Labels of the issue
+ """
+ labels: [String!]
+
+ """
+ The ID of milestone to be assigned to the board.
+ """
+ milestoneId: MilestoneID
+
+ """
The board name.
"""
name: String
@@ -4004,6 +4034,11 @@ input CreateBoardInput {
The project full path the resource is associated with
"""
projectPath: ID
+
+ """
+ The weight value to be assigned to the board.
+ """
+ weight: Int
}
"""
@@ -8063,12 +8098,37 @@ Represents an epic board
"""
type EpicBoard {
"""
- Global ID of the board
+ Global ID of the board.
"""
id: BoardsEpicBoardID!
"""
- Name of the board
+ Epic board lists.
+ """
+ lists(
+ """
+ Returns the elements in the list that come after the specified cursor.
+ """
+ after: String
+
+ """
+ Returns the elements in the list that come before the specified cursor.
+ """
+ before: String
+
+ """
+ Returns the first _n_ elements from the list.
+ """
+ first: Int
+
+ """
+ Returns the last _n_ elements from the list.
+ """
+ last: Int
+ ): EpicListConnection
+
+ """
+ Name of the board.
"""
name: String
}
@@ -8664,6 +8724,71 @@ type EpicIssueEdge {
}
"""
+Represents an epic board list
+"""
+type EpicList {
+ """
+ Global ID of the board list.
+ """
+ id: BoardsEpicListID!
+
+ """
+ Label of the list.
+ """
+ label: Label
+
+ """
+ Type of the list.
+ """
+ listType: String!
+
+ """
+ Position of the list within the board.
+ """
+ position: Int
+
+ """
+ Title of the list.
+ """
+ title: String!
+}
+
+"""
+The connection type for EpicList.
+"""
+type EpicListConnection {
+ """
+ A list of edges.
+ """
+ edges: [EpicListEdge]
+
+ """
+ A list of nodes.
+ """
+ nodes: [EpicList]
+
+ """
+ Information to aid in pagination.
+ """
+ pageInfo: PageInfo!
+}
+
+"""
+An edge in a connection.
+"""
+type EpicListEdge {
+ """
+ A cursor for use in pagination.
+ """
+ cursor: String!
+
+ """
+ The item at the end of the edge.
+ """
+ node: EpicList
+}
+
+"""
Check permissions for the current user on an epic
"""
type EpicPermissions {
@@ -10265,7 +10390,7 @@ type Group {
reportType: [VulnerabilityReportType!]
"""
- Filter vulnerabilities by scanner
+ Filter vulnerabilities by VulnerabilityScanner.externalId
"""
scanner: [String!]
@@ -17843,7 +17968,7 @@ type Project {
reportType: [VulnerabilityReportType!]
"""
- Filter vulnerabilities by scanner
+ Filter vulnerabilities by VulnerabilityScanner.externalId
"""
scanner: [String!]
@@ -19031,7 +19156,7 @@ type Query {
reportType: [VulnerabilityReportType!]
"""
- Filter vulnerabilities by scanner
+ Filter vulnerabilities by VulnerabilityScanner.externalId
"""
scanner: [String!]
@@ -23395,6 +23520,11 @@ Autogenerated input type of UpdateBoard
"""
input UpdateBoardInput {
"""
+ The ID of user to be assigned to the board.
+ """
+ assigneeId: UserID
+
+ """
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
@@ -23415,9 +23545,34 @@ input UpdateBoardInput {
id: BoardID!
"""
+ The ID of iteration to be assigned to the board.
+ """
+ iterationId: IterationID
+
+ """
+ The IDs of labels to be added to the board.
+ """
+ labelIds: [LabelID!]
+
+ """
+ Labels of the issue
+ """
+ labels: [String!]
+
+ """
+ The ID of milestone to be assigned to the board.
+ """
+ milestoneId: MilestoneID
+
+ """
The board name.
"""
name: String
+
+ """
+ The weight value to be assigned to the board.
+ """
+ weight: Int
}
"""
diff --git a/doc/api/graphql/reference/gitlab_schema.json b/doc/api/graphql/reference/gitlab_schema.json
index 4adb92d351e..e1fe89e192a 100644
--- a/doc/api/graphql/reference/gitlab_schema.json
+++ b/doc/api/graphql/reference/gitlab_schema.json
@@ -5901,6 +5901,16 @@
},
{
"kind": "SCALAR",
+ "name": "BoardsEpicListID",
+ "description": "Identifier of Boards::EpicList",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "SCALAR",
"name": "Boolean",
"description": "Represents `true` or `false` values.",
"fields": null,
@@ -10965,6 +10975,82 @@
"defaultValue": null
},
{
+ "name": "assigneeId",
+ "description": "The ID of user to be assigned to the board.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "UserID",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "milestoneId",
+ "description": "The ID of milestone to be assigned to the board.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "MilestoneID",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "iterationId",
+ "description": "The ID of iteration to be assigned to the board.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "IterationID",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "weight",
+ "description": "The weight value to be assigned to the board.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "labels",
+ "description": "Labels of the issue",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "labelIds",
+ "description": "The IDs of labels to be added to the board.",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "LabelID",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ },
+ {
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"type": {
@@ -22557,7 +22643,7 @@
"fields": [
{
"name": "id",
- "description": "Global ID of the board",
+ "description": "Global ID of the board.",
"args": [
],
@@ -22574,8 +22660,61 @@
"deprecationReason": null
},
{
+ "name": "lists",
+ "description": "Epic board lists.",
+ "args": [
+ {
+ "name": "after",
+ "description": "Returns the elements in the list that come after the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "before",
+ "description": "Returns the elements in the list that come before the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "first",
+ "description": "Returns the first _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "last",
+ "description": "Returns the last _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "EpicListConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "name",
- "description": "Name of the board",
+ "description": "Name of the board.",
"args": [
],
@@ -24301,6 +24440,213 @@
},
{
"kind": "OBJECT",
+ "name": "EpicList",
+ "description": "Represents an epic board list",
+ "fields": [
+ {
+ "name": "id",
+ "description": "Global ID of the board list.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "BoardsEpicListID",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "label",
+ "description": "Label of the list.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "Label",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "listType",
+ "description": "Type of the list.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "position",
+ "description": "Position of the list within the board.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "title",
+ "description": "Title of the list.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "EpicListConnection",
+ "description": "The connection type for EpicList.",
+ "fields": [
+ {
+ "name": "edges",
+ "description": "A list of edges.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "EpicListEdge",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "nodes",
+ "description": "A list of nodes.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "EpicList",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "pageInfo",
+ "description": "Information to aid in pagination.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "PageInfo",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "EpicListEdge",
+ "description": "An edge in a connection.",
+ "fields": [
+ {
+ "name": "cursor",
+ "description": "A cursor for use in pagination.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "node",
+ "description": "The item at the end of the edge.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "EpicList",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
"name": "EpicPermissions",
"description": "Check permissions for the current user on an epic",
"fields": [
@@ -28185,7 +28531,7 @@
},
{
"name": "scanner",
- "description": "Filter vulnerabilities by scanner",
+ "description": "Filter vulnerabilities by VulnerabilityScanner.externalId",
"type": {
"kind": "LIST",
"name": null,
@@ -52204,7 +52550,7 @@
},
{
"name": "scanner",
- "description": "Filter vulnerabilities by scanner",
+ "description": "Filter vulnerabilities by VulnerabilityScanner.externalId",
"type": {
"kind": "LIST",
"name": null,
@@ -55577,7 +55923,7 @@
},
{
"name": "scanner",
- "description": "Filter vulnerabilities by scanner",
+ "description": "Filter vulnerabilities by VulnerabilityScanner.externalId",
"type": {
"kind": "LIST",
"name": null,
@@ -68572,6 +68918,82 @@
"defaultValue": null
},
{
+ "name": "assigneeId",
+ "description": "The ID of user to be assigned to the board.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "UserID",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "milestoneId",
+ "description": "The ID of milestone to be assigned to the board.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "MilestoneID",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "iterationId",
+ "description": "The ID of iteration to be assigned to the board.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "IterationID",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "weight",
+ "description": "The weight value to be assigned to the board.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "labels",
+ "description": "Labels of the issue",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "labelIds",
+ "description": "The IDs of labels to be added to the board.",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "LabelID",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ },
+ {
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"type": {
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 2842f7893bf..b542e10dd5c 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -1377,8 +1377,9 @@ Represents an epic board.
| Field | Type | Description |
| ----- | ---- | ----------- |
-| `id` | BoardsEpicBoardID! | Global ID of the board |
-| `name` | String | Name of the board |
+| `id` | BoardsEpicBoardID! | Global ID of the board. |
+| `lists` | EpicListConnection | Epic board lists. |
+| `name` | String | Name of the board. |
### EpicDescendantCount
@@ -1472,6 +1473,18 @@ Relationship between an epic and an issue.
| `webUrl` | String! | Web URL of the issue |
| `weight` | Int | Weight of the issue. |
+### EpicList
+
+Represents an epic board list.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `id` | BoardsEpicListID! | Global ID of the board list. |
+| `label` | Label | Label of the list. |
+| `listType` | String! | Type of the list. |
+| `position` | Int | Position of the list within the board. |
+| `title` | String! | Title of the list. |
+
### EpicPermissions
Check permissions for the current user on an epic.
diff --git a/doc/ci/examples/authenticating-with-hashicorp-vault/index.md b/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
index b7f59761889..2f54e80facc 100644
--- a/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
+++ b/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
@@ -47,6 +47,7 @@ The JWT's payload looks like this:
"project_id": "22", #
"project_path": "mygroup/myproject", #
"user_id": "42", # Id of the user executing the job
+ "user_login": "myuser" # GitLab @username
"user_email": "myuser@example.com", # Email of the user executing the job
"pipeline_id": "1212", #
"job_id": "1212", #
diff --git a/doc/development/documentation/styleguide/index.md b/doc/development/documentation/styleguide/index.md
index 971652f76d3..878a6a55216 100644
--- a/doc/development/documentation/styleguide/index.md
+++ b/doc/development/documentation/styleguide/index.md
@@ -528,7 +528,7 @@ You can use the following fake tokens as examples:
| Usage | Guidance |
|-----------------------|-----|
-| admin, admin area | Use **administration**, **administrator**, **administer**, or **Admin Area** instead. |.
+| admin, admin area | Use **administration**, **administrator**, **administer**, or **Admin Area** instead. |
| and/or | Use **or** instead, or another sensible construction. |
| currently | Do not use when talking about the product or its features. The documentation describes the product as it is today. |
| easily | Do not use. If the user doesn't find the process to be these things, we lose their trust. |
diff --git a/doc/development/iterating_tables_in_batches.md b/doc/development/iterating_tables_in_batches.md
index 3953e7097dd..43d7f32ad7f 100644
--- a/doc/development/iterating_tables_in_batches.md
+++ b/doc/development/iterating_tables_in_batches.md
@@ -42,6 +42,29 @@ The API of this method is similar to `in_batches`, though it doesn't support
all of the arguments that `in_batches` supports. You should always use
`each_batch` _unless_ you have a specific need for `in_batches`.
+## Avoid iterating over non-unique columns
+
+One should proceed with extra caution, and possibly avoid iterating over a column that can contain duplicate values.
+When you iterate over an attribute that is not unique, even with the applied max batch size, there is no guarantee that the resulting batches will not surpass it.
+The following snippet demonstrates this situation, whe one attempt to select `Ci::Build` entries for users with `id` between `1` and `10,s000`, database returns `1 215 178`
+matching rows
+
+```ruby
+[ gstg ] production> Ci::Build.where(user_id: (1..10_000)).size
+=> 1215178
+```
+
+This happens because built relation is translated into following query
+
+```ruby
+[ gstg ] production> puts Ci::Build.where(user_id: (1..10_000)).to_sql
+SELECT "ci_builds".* FROM "ci_builds" WHERE "ci_builds"."type" = 'Ci::Build' AND "ci_builds"."user_id" BETWEEN 1 AND 10000
+=> nil
+```
+
+And queries which filters non-unique column by range `WHERE "ci_builds"."user_id" BETWEEN ? AND ?`, even though the range size is limited to certain threshold (`10,000` in previous example) this threshold does not translates to the size of returned dataset. That happens because when taking `n` possible values of attributes,
+one can't tell for sure that the number of records that contains them will be less than `n`.
+
## Column definition
`EachBatch` uses the primary key of the model by default for the iteration. This works most of the cases, however in some cases, you might want to use a different column for the iteration.
@@ -55,7 +78,7 @@ end
The query above iterates over the project creators and prints them out without duplications.
NOTE:
-In case the column is not unique (no unique index definition), calling the `distinct` method on the relation is necessary.
+In case the column is not unique (no unique index definition), calling the `distinct` method on the relation is necessary. Using not unique column without `distinct` may result in `each_batch` falling into endless loop as described at following [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/285097)
## `EachBatch` in data migrations
diff --git a/doc/development/product_analytics/usage_ping.md b/doc/development/product_analytics/usage_ping.md
index 37363bbabbc..900fb50b89b 100644
--- a/doc/development/product_analytics/usage_ping.md
+++ b/doc/development/product_analytics/usage_ping.md
@@ -196,6 +196,9 @@ Arguments:
- `start`: custom start of the batch counting in order to avoid complex min calculations
- `end`: custom end of the batch counting in order to avoid complex min calculations
+WARNING:
+Counting over non-unique columns can lead to performance issues. Take a look at the [iterating tables in batches](../iterating_tables_in_batches.md) guide for more details.
+
Examples:
```ruby
diff --git a/doc/user/application_security/dependency_scanning/index.md b/doc/user/application_security/dependency_scanning/index.md
index 07774f51958..debad3c4de7 100644
--- a/doc/user/application_security/dependency_scanning/index.md
+++ b/doc/user/application_security/dependency_scanning/index.md
@@ -64,7 +64,8 @@ The following languages and dependency managers are supported:
| [Conan](https://conan.io/) | C, C++ | [`conan.lock`](https://docs.conan.io/en/latest/versioning/lockfiles.html) | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) |
| [Golang](https://golang.org/) | Go | `go.sum` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) |
| [Gradle](https://gradle.org/), [Maven](https://maven.apache.org/) | Java | `build.gradle`, `build.gradle.kts`, `pom.xml` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) |
-| [npm](https://www.npmjs.com/), [yarn](https://classic.yarnpkg.com/en/) 1.x | JavaScript | `package-lock.json`, `npm-shrinkwrap.json`, `yarn.lock` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium), [Retire.js](https://retirejs.github.io/retire.js/) |
+| [npm](https://www.npmjs.com/), [yarn](https://classic.yarnpkg.com/en/) 1.x | JavaScript | `package-lock.json`, `npm-shrinkwrap.json`, `yarn.lock` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) |
+| [npm](https://www.npmjs.com/), [yarn](https://classic.yarnpkg.com/en/) 1.x | JavaScript | `package.json` | [Retire.js](https://retirejs.github.io/retire.js/) |
| [NuGet](https://www.nuget.org/) 4.9+ | .NET, C# | [`packages.lock.json`](https://docs.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files#enabling-lock-file) | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) |
| [setuptools](https://setuptools.readthedocs.io/en/latest/), [pip](https://pip.pypa.io/en/stable/), [Pipenv](https://pipenv.pypa.io/en/latest/) | Python | `setup.py`, `requirements.txt`, `requirements.pip`, `requires.txt`, `Pipfile` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) |
| [sbt](https://www.scala-sbt.org/) 1.2 and below ([Ivy](http://ant.apache.org/ivy/)) | Scala | `build.sbt` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) |
@@ -115,7 +116,7 @@ include:
- template: Dependency-Scanning.gitlab-ci.yml
variables:
- DS_PYTHON_VERSION: 2
+ SECURE_LOG_LEVEL: error
```
Because template is [evaluated before](../../../ci/yaml/README.md#include) the pipeline
diff --git a/lib/feature/shared.rb b/lib/feature/shared.rb
index a3f02156d94..17dfe26bd82 100644
--- a/lib/feature/shared.rb
+++ b/lib/feature/shared.rb
@@ -57,8 +57,6 @@ class Feature
default_enabled: false,
example: <<-EOS
experiment(:my_experiment, project: project, actor: current_user) { ...variant code... }
- # or
- Gitlab::Experimentation.in_experiment_group?(:my_experiment, subject: current_user)
EOS
}
}.freeze
diff --git a/lib/gitlab/experimentation/experiment.rb b/lib/gitlab/experimentation/experiment.rb
index b9eda0cfc31..e594c3bedeb 100644
--- a/lib/gitlab/experimentation/experiment.rb
+++ b/lib/gitlab/experimentation/experiment.rb
@@ -3,8 +3,6 @@
module Gitlab
module Experimentation
class Experiment
- FEATURE_FLAG_SUFFIX = "_experiment_percentage"
-
attr_reader :key, :tracking_category, :use_backwards_compatible_subject_index
def initialize(key, **params)
@@ -12,7 +10,7 @@ module Gitlab
@tracking_category = params[:tracking_category]
@use_backwards_compatible_subject_index = params[:use_backwards_compatible_subject_index]
- @experiment_percentage = Feature.get(:"#{key}#{FEATURE_FLAG_SUFFIX}").percentage_of_time_value # rubocop:disable Gitlab/AvoidFeatureGet
+ @experiment_percentage = Feature.get(:"#{key}_experiment_percentage").percentage_of_time_value # rubocop:disable Gitlab/AvoidFeatureGet
end
def active?
diff --git a/lib/gitlab/quick_actions/merge_request_actions.rb b/lib/gitlab/quick_actions/merge_request_actions.rb
index 1986b7a1789..aafd493549b 100644
--- a/lib/gitlab/quick_actions/merge_request_actions.rb
+++ b/lib/gitlab/quick_actions/merge_request_actions.rb
@@ -9,48 +9,30 @@ module Gitlab
included do
# MergeRequest only quick actions definitions
desc do
- if Feature.enabled?(:merge_orchestration_service, quick_action_target.project, default_enabled: true)
- if preferred_strategy = preferred_auto_merge_strategy(quick_action_target)
- _("Merge automatically (%{strategy})") % { strategy: preferred_strategy.humanize }
- else
- _("Merge immediately")
- end
+ if preferred_strategy = preferred_auto_merge_strategy(quick_action_target)
+ _("Merge automatically (%{strategy})") % { strategy: preferred_strategy.humanize }
else
- _('Merge (when the pipeline succeeds)')
+ _("Merge immediately")
end
end
explanation do
- if Feature.enabled?(:merge_orchestration_service, quick_action_target.project, default_enabled: true)
- if preferred_strategy = preferred_auto_merge_strategy(quick_action_target)
- _("Schedules to merge this merge request (%{strategy}).") % { strategy: preferred_strategy.humanize }
- else
- _('Merges this merge request immediately.')
- end
+ if preferred_strategy = preferred_auto_merge_strategy(quick_action_target)
+ _("Schedules to merge this merge request (%{strategy}).") % { strategy: preferred_strategy.humanize }
else
- _('Merges this merge request when the pipeline succeeds.')
+ _('Merges this merge request immediately.')
end
end
execution_message do
- if Feature.enabled?(:merge_orchestration_service, quick_action_target.project, default_enabled: true)
- if preferred_strategy = preferred_auto_merge_strategy(quick_action_target)
- _("Scheduled to merge this merge request (%{strategy}).") % { strategy: preferred_strategy.humanize }
- else
- _('Merged this merge request.')
- end
+ if preferred_strategy = preferred_auto_merge_strategy(quick_action_target)
+ _("Scheduled to merge this merge request (%{strategy}).") % { strategy: preferred_strategy.humanize }
else
- _('Scheduled to merge this merge request when the pipeline succeeds.')
+ _('Merged this merge request.')
end
end
types MergeRequest
condition do
- if Feature.enabled?(:merge_orchestration_service, quick_action_target.project, default_enabled: true)
- quick_action_target.persisted? &&
- merge_orchestration_service.can_merge?(quick_action_target)
- else
- last_diff_sha = params && params[:merge_request_diff_head_sha]
- quick_action_target.persisted? &&
- quick_action_target.mergeable_with_quick_action?(current_user, autocomplete_precheck: !last_diff_sha, last_diff_sha: last_diff_sha)
- end
+ quick_action_target.persisted? &&
+ merge_orchestration_service.can_merge?(quick_action_target)
end
command :merge do
@updates[:merge] = params[:merge_request_diff_head_sha]
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index cd622919149..0ac2bdacc40 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -17263,9 +17263,6 @@ msgstr ""
msgid "Merge"
msgstr ""
-msgid "Merge (when the pipeline succeeds)"
-msgstr ""
-
msgid "Merge Conflicts"
msgstr ""
@@ -17506,9 +17503,6 @@ msgstr ""
msgid "Merges this merge request immediately."
msgstr ""
-msgid "Merges this merge request when the pipeline succeeds."
-msgstr ""
-
msgid "Merging immediately isn't recommended as it may negatively impact the existing merge train. Read the %{docsLinkStart}documentation%{docsLinkEnd} for more information."
msgstr ""
@@ -24211,9 +24205,6 @@ msgstr ""
msgid "Scheduled to merge this merge request (%{strategy})."
msgstr ""
-msgid "Scheduled to merge this merge request when the pipeline succeeds."
-msgstr ""
-
msgid "Schedules"
msgstr ""
@@ -28722,6 +28713,9 @@ msgstr ""
msgid "ThreatMonitoring|Environment"
msgstr ""
+msgid "ThreatMonitoring|Hide dismissed alerts"
+msgstr ""
+
msgid "ThreatMonitoring|In review"
msgstr ""
@@ -29929,7 +29923,7 @@ msgstr ""
msgid "UpdateProject|Project could not be updated!"
msgstr ""
-msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{container_full_path} - %{message}"
msgstr ""
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
diff --git a/spec/controllers/explore/projects_controller_spec.rb b/spec/controllers/explore/projects_controller_spec.rb
index 4ec890a528f..cfbd129388d 100644
--- a/spec/controllers/explore/projects_controller_spec.rb
+++ b/spec/controllers/explore/projects_controller_spec.rb
@@ -60,7 +60,7 @@ RSpec.describe Explore::ProjectsController do
end
shared_examples "blocks high page numbers" do
- let(:page_limit) { 200 }
+ let(:page_limit) { described_class::PAGE_LIMIT }
context "page number is too high" do
[:index, :trending, :starred].each do |endpoint|
diff --git a/spec/finders/ci/daily_build_group_report_results_finder_spec.rb b/spec/finders/ci/daily_build_group_report_results_finder_spec.rb
index 28a732fda82..2a6e44673e3 100644
--- a/spec/finders/ci/daily_build_group_report_results_finder_spec.rb
+++ b/spec/finders/ci/daily_build_group_report_results_finder_spec.rb
@@ -64,13 +64,13 @@ RSpec.describe Ci::DailyBuildGroupReportResultsFinder do
end
end
- context 'when ref_path is not present' do
+ context 'when ref_path query parameter is not present' do
let(:ref_path) { nil }
- context 'when coverages exist for the default branch' do
+ context 'when records with cover data from the default branch exist' do
let(:default_branch) { true }
- it 'returns coverage for the default branch' do
+ it 'returns records with default_branch:true, irrespective of ref_path' do
rspec_coverage_4 = create_daily_coverage('rspec', 66.0, '2020-03-10')
expect(coverages).to contain_exactly(rspec_coverage_4)
diff --git a/spec/frontend/issue_show/components/app_spec.js b/spec/frontend/issue_show/components/app_spec.js
index dde4e8458d5..d50b67970d8 100644
--- a/spec/frontend/issue_show/components/app_spec.js
+++ b/spec/frontend/issue_show/components/app_spec.js
@@ -507,13 +507,6 @@ describe('Issuable output', () => {
expect(wrapper.vm.issueChanged).toBe(false);
});
- it('returns false when `initialTitleText` is null and `formState.title` is empty string', () => {
- wrapper.vm.store.formState.title = '';
- wrapper.setProps({ initialTitleText: null });
-
- expect(wrapper.vm.issueChanged).toBe(false);
- });
-
it('returns true when description is changed', () => {
wrapper.vm.store.formState.description = 'RandomText';
diff --git a/spec/frontend/sentry_error_stack_trace/components/sentry_error_stack_trace_spec.js b/spec/frontend/sentry_error_stack_trace/components/sentry_error_stack_trace_spec.js
index e5f83b6fa49..135a3844e78 100644
--- a/spec/frontend/sentry_error_stack_trace/components/sentry_error_stack_trace_spec.js
+++ b/spec/frontend/sentry_error_stack_trace/components/sentry_error_stack_trace_spec.js
@@ -78,10 +78,5 @@ describe('Sentry Error Stack Trace', () => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
expect(wrapper.find(Stacktrace).exists()).toBe(true);
});
-
- it('should not show stacktrace if it does not exist', () => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
- expect(wrapper.find(Stacktrace).exists()).toBe(false);
- });
});
});
diff --git a/spec/frontend_integration/ide/helpers/ide_helper.js b/spec/frontend_integration/ide/helpers/ide_helper.js
index fe8d5f93794..7ae7c4cb0b6 100644
--- a/spec/frontend_integration/ide/helpers/ide_helper.js
+++ b/spec/frontend_integration/ide/helpers/ide_helper.js
@@ -45,9 +45,9 @@ export const getEditorValue = async () => {
return window.monaco.editor.getModel(uri).getValue();
};
-const findTreeBody = () => screen.findByTestId('ide-tree-body', {}, { timeout: 5000 });
+const findTreeBody = () => screen.findByTestId('ide-tree-body');
-const findRootActions = () => screen.findByTestId('ide-root-actions', {}, { timeout: 7000 });
+const findRootActions = () => screen.findByTestId('ide-root-actions');
const findFileRowContainer = (row = null) =>
row ? Promise.resolve(row.parentElement) : findTreeBody();
diff --git a/spec/frontend_integration/ide/user_opens_file_spec.js b/spec/frontend_integration/ide/user_opens_file_spec.js
index 98a73c7a029..7fa6dcecc9e 100644
--- a/spec/frontend_integration/ide/user_opens_file_spec.js
+++ b/spec/frontend_integration/ide/user_opens_file_spec.js
@@ -3,9 +3,7 @@ import { screen } from '@testing-library/dom';
import * as ideHelper from './helpers/ide_helper';
import startWebIDE from './helpers/start';
-// https://gitlab.com/gitlab-org/gitlab/-/issues/293654#note_466432769
-// eslint-disable-next-line jest/no-disabled-tests
-describe.skip('IDE: User opens a file in the Web IDE', () => {
+describe('IDE: User opens a file in the Web IDE', () => {
useOverclockTimers();
let vm;
diff --git a/spec/frontend_integration/test_helpers/setup/index.js b/spec/frontend_integration/test_helpers/setup/index.js
index ba1d256e16e..946ccbec00c 100644
--- a/spec/frontend_integration/test_helpers/setup/index.js
+++ b/spec/frontend_integration/test_helpers/setup/index.js
@@ -3,3 +3,4 @@ import './setup_globals';
import './setup_axios';
import './setup_serializers';
import './setup_mock_server';
+import './setup_testing_library';
diff --git a/spec/frontend_integration/test_helpers/setup/setup_testing_library.js b/spec/frontend_integration/test_helpers/setup/setup_testing_library.js
new file mode 100644
index 00000000000..5081b1c3b62
--- /dev/null
+++ b/spec/frontend_integration/test_helpers/setup/setup_testing_library.js
@@ -0,0 +1,3 @@
+import { configure } from '@testing-library/dom';
+
+configure({ asyncUtilTimeout: 10000 });
diff --git a/spec/lib/banzai/filter/reference_redactor_filter_spec.rb b/spec/lib/banzai/filter/reference_redactor_filter_spec.rb
index ac1cabb34cc..d0336e9e059 100644
--- a/spec/lib/banzai/filter/reference_redactor_filter_spec.rb
+++ b/spec/lib/banzai/filter/reference_redactor_filter_spec.rb
@@ -143,15 +143,32 @@ RSpec.describe Banzai::Filter::ReferenceRedactorFilter do
expect(doc.css('a').length).to eq 1
end
- it 'allows references for admin' do
- admin = create(:admin)
- project = create(:project, :public)
- issue = create(:issue, :confidential, project: project)
- link = reference_link(project: project.id, issue: issue.id, reference_type: 'issue')
+ context 'for admin' do
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it 'allows references' do
+ admin = create(:admin)
+ project = create(:project, :public)
+ issue = create(:issue, :confidential, project: project)
+ link = reference_link(project: project.id, issue: issue.id, reference_type: 'issue')
+
+ doc = filter(link, current_user: admin)
+
+ expect(doc.css('a').length).to eq 1
+ end
+ end
- doc = filter(link, current_user: admin)
+ context 'when admin mode is disabled' do
+ it 'removes references' do
+ admin = create(:admin)
+ project = create(:project, :public)
+ issue = create(:issue, :confidential, project: project)
+ link = reference_link(project: project.id, issue: issue.id, reference_type: 'issue')
- expect(doc.css('a').length).to eq 1
+ doc = filter(link, current_user: admin)
+
+ expect(doc.css('a').length).to eq 0
+ end
+ end
end
context "when a confidential issue is moved from a public project to a private one" do
diff --git a/spec/lib/constraints/admin_constrainer_spec.rb b/spec/lib/constraints/admin_constrainer_spec.rb
index 3efe683177c..ac6ad31120e 100644
--- a/spec/lib/constraints/admin_constrainer_spec.rb
+++ b/spec/lib/constraints/admin_constrainer_spec.rb
@@ -2,7 +2,7 @@
#
require 'spec_helper'
-RSpec.describe Constraints::AdminConstrainer, :do_not_mock_admin_mode do
+RSpec.describe Constraints::AdminConstrainer do
let(:user) { create(:user) }
let(:session) { {} }
diff --git a/spec/lib/gitlab/auth/current_user_mode_spec.rb b/spec/lib/gitlab/auth/current_user_mode_spec.rb
index ffd7813190a..a21f0931b78 100644
--- a/spec/lib/gitlab/auth/current_user_mode_spec.rb
+++ b/spec/lib/gitlab/auth/current_user_mode_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::Auth::CurrentUserMode, :do_not_mock_admin_mode, :request_store do
+RSpec.describe Gitlab::Auth::CurrentUserMode, :request_store do
let(:user) { build_stubbed(:user) }
subject { described_class.new(user) }
diff --git a/spec/lib/gitlab/ci/templates/AWS/deploy_ecs_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/AWS/deploy_ecs_gitlab_ci_yaml_spec.rb
index 4be92e8608e..653b3be0b2a 100644
--- a/spec/lib/gitlab/ci/templates/AWS/deploy_ecs_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/AWS/deploy_ecs_gitlab_ci_yaml_spec.rb
@@ -6,10 +6,10 @@ RSpec.describe 'Deploy-ECS.gitlab-ci.yml' do
subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('AWS/Deploy-ECS') }
describe 'the created pipeline' do
- let_it_be(:user) { create(:admin) }
let(:default_branch) { 'master' }
let(:pipeline_branch) { default_branch }
let(:project) { create(:project, :auto_devops, :custom_repo, files: { 'README.md' => '' }) }
+ let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
let(:pipeline) { service.execute!(:push) }
let(:build_names) { pipeline.builds.pluck(:name) }
diff --git a/spec/lib/gitlab/ci/templates/Jobs/build_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Jobs/build_gitlab_ci_yaml_spec.rb
index 4f8faa5ddb1..1f278048ad5 100644
--- a/spec/lib/gitlab/ci/templates/Jobs/build_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Jobs/build_gitlab_ci_yaml_spec.rb
@@ -6,8 +6,8 @@ RSpec.describe 'Jobs/Build.gitlab-ci.yml' do
subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('Jobs/Build') }
describe 'the created pipeline' do
- let_it_be(:user) { create(:admin) }
let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { project.owner }
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
diff --git a/spec/lib/gitlab/ci/templates/Jobs/code_quality_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Jobs/code_quality_gitlab_ci_yaml_spec.rb
index e685ad3b46e..0a76de82421 100644
--- a/spec/lib/gitlab/ci/templates/Jobs/code_quality_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Jobs/code_quality_gitlab_ci_yaml_spec.rb
@@ -6,8 +6,8 @@ RSpec.describe 'Jobs/Code-Quality.gitlab-ci.yml' do
subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('Jobs/Code-Quality') }
describe 'the created pipeline' do
- let_it_be(:user) { create(:admin) }
let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { project.owner }
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
diff --git a/spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb
index ea9bd5bd02c..25c88c161ea 100644
--- a/spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb
@@ -27,8 +27,8 @@ RSpec.describe 'Jobs/Deploy.gitlab-ci.yml' do
end
describe 'the created pipeline' do
- let(:user) { create(:admin) }
let(:project) { create(:project, :repository) }
+ let(:user) { project.owner }
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
diff --git a/spec/lib/gitlab/ci/templates/Jobs/test_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Jobs/test_gitlab_ci_yaml_spec.rb
index f475785be98..b64959a9917 100644
--- a/spec/lib/gitlab/ci/templates/Jobs/test_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Jobs/test_gitlab_ci_yaml_spec.rb
@@ -6,8 +6,8 @@ RSpec.describe 'Jobs/Test.gitlab-ci.yml' do
subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('Jobs/Test') }
describe 'the created pipeline' do
- let_it_be(:user) { create(:admin) }
let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { project.owner }
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
diff --git a/spec/lib/gitlab/ci/templates/Terraform/base_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Terraform/base_gitlab_ci_yaml_spec.rb
index 8df739d9245..0811c07e896 100644
--- a/spec/lib/gitlab/ci/templates/Terraform/base_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Terraform/base_gitlab_ci_yaml_spec.rb
@@ -6,10 +6,10 @@ RSpec.describe 'Terraform/Base.latest.gitlab-ci.yml' do
subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('Terraform/Base.latest') }
describe 'the created pipeline' do
- let(:user) { create(:admin) }
let(:default_branch) { 'master' }
let(:pipeline_branch) { default_branch }
let(:project) { create(:project, :custom_repo, files: { 'README.md' => '' }) }
+ let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
let(:pipeline) { service.execute!(:push) }
let(:build_names) { pipeline.builds.pluck(:name) }
diff --git a/spec/lib/gitlab/ci/templates/Verify/load_performance_testing_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Verify/load_performance_testing_gitlab_ci_yaml_spec.rb
index 9711df55226..03fa45fe0a1 100644
--- a/spec/lib/gitlab/ci/templates/Verify/load_performance_testing_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Verify/load_performance_testing_gitlab_ci_yaml_spec.rb
@@ -19,8 +19,8 @@ RSpec.describe 'Verify/Load-Performance-Testing.gitlab-ci.yml' do
end
describe 'the created pipeline' do
- let(:user) { create(:admin) }
let(:project) { create(:project, :repository) }
+ let(:user) { project.owner }
let(:default_branch) { 'master' }
let(:pipeline_ref) { default_branch }
diff --git a/spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb
index 793df55f45d..f9d6fe24e70 100644
--- a/spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb
@@ -6,10 +6,10 @@ RSpec.describe 'Auto-DevOps.gitlab-ci.yml' do
subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('Auto-DevOps') }
describe 'the created pipeline' do
- let(:user) { create(:admin) }
let(:default_branch) { 'master' }
let(:pipeline_branch) { default_branch }
let(:project) { create(:project, :auto_devops, :custom_repo, files: { 'README.md' => '' }) }
+ let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
let(:pipeline) { service.execute!(:push) }
let(:build_names) { pipeline.builds.pluck(:name) }
@@ -232,8 +232,8 @@ RSpec.describe 'Auto-DevOps.gitlab-ci.yml' do
end
with_them do
- let(:user) { create(:admin) }
let(:project) { create(:project, :custom_repo, files: files) }
+ let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: 'master' ) }
let(:pipeline) { service.execute(:push) }
let(:build_names) { pipeline.builds.pluck(:name) }
diff --git a/spec/lib/gitlab/ci/templates/flutter_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/flutter_gitlab_ci_yaml_spec.rb
index e0e3ed2f063..4e5fe622648 100644
--- a/spec/lib/gitlab/ci/templates/flutter_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/flutter_gitlab_ci_yaml_spec.rb
@@ -6,10 +6,9 @@ RSpec.describe 'Flutter.gitlab-ci.yml' do
subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('Flutter') }
describe 'the created pipeline' do
- let_it_be(:user) { create(:admin) }
-
let(:pipeline_branch) { 'master' }
let(:project) { create(:project, :custom_repo, files: { 'README.md' => '' }) }
+ let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
let(:pipeline) { service.execute!(:push) }
let(:build_names) { pipeline.builds.pluck(:name) }
diff --git a/spec/lib/gitlab/ci/templates/npm_spec.rb b/spec/lib/gitlab/ci/templates/npm_spec.rb
index 1f8e32ce019..b10e2b0e057 100644
--- a/spec/lib/gitlab/ci/templates/npm_spec.rb
+++ b/spec/lib/gitlab/ci/templates/npm_spec.rb
@@ -6,11 +6,10 @@ RSpec.describe 'npm.latest.gitlab-ci.yml' do
subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('npm.latest') }
describe 'the created pipeline' do
- let_it_be(:user) { create(:admin) }
-
let(:repo_files) { { 'package.json' => '{}', 'README.md' => '' } }
let(:modified_files) { %w[package.json] }
let(:project) { create(:project, :custom_repo, files: repo_files) }
+ let(:user) { project.owner }
let(:pipeline_branch) { project.default_branch }
let(:pipeline_tag) { 'v1.2.1' }
let(:pipeline_ref) { pipeline_branch }
diff --git a/spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb
index 5eec021b9d7..4377f155d34 100644
--- a/spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb
@@ -10,11 +10,10 @@ RSpec.describe 'Terraform.latest.gitlab-ci.yml' do
subject(:template) { Gitlab::Template::GitlabCiYmlTemplate.find('Terraform.latest') }
describe 'the created pipeline' do
- let_it_be(:user) { create(:admin) }
-
let(:default_branch) { 'master' }
let(:pipeline_branch) { default_branch }
let(:project) { create(:project, :custom_repo, files: { 'README.md' => '' }) }
+ let(:user) { project.owner }
let(:service) { Ci::CreatePipelineService.new(project, user, ref: pipeline_branch ) }
let(:pipeline) { service.execute!(:push) }
let(:build_names) { pipeline.builds.pluck(:name) }
diff --git a/spec/lib/gitlab/cycle_analytics/base_event_fetcher_spec.rb b/spec/lib/gitlab/cycle_analytics/base_event_fetcher_spec.rb
index 056c1b5bc9f..c770acb88f4 100644
--- a/spec/lib/gitlab/cycle_analytics/base_event_fetcher_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/base_event_fetcher_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::CycleAnalytics::BaseEventFetcher do
let(:max_events) { 2 }
let(:project) { create(:project, :repository) }
- let(:user) { create(:user, :admin) }
+ let(:user) { project.owner }
let(:start_time_attrs) { Issue.arel_table[:created_at] }
let(:end_time_attrs) { [Issue::Metrics.arel_table[:first_associated_with_milestone_at]] }
let(:options) do
diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb
index 553f33a66c4..ed91ce519d5 100644
--- a/spec/lib/gitlab/cycle_analytics/events_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe 'value stream analytics events', :aggregate_failures do
let_it_be(:project) { create(:project, :repository) }
- let_it_be(:user) { create(:user, :admin) }
+ let_it_be(:user) { project.owner }
let(:from_date) { 10.days.ago }
let!(:context) { create(:issue, project: project, created_at: 2.days.ago) }
diff --git a/spec/lib/gitlab/git_access_snippet_spec.rb b/spec/lib/gitlab/git_access_snippet_spec.rb
index f5d8758a78a..3deccc911e5 100644
--- a/spec/lib/gitlab/git_access_snippet_spec.rb
+++ b/spec/lib/gitlab/git_access_snippet_spec.rb
@@ -172,7 +172,7 @@ RSpec.describe Gitlab::GitAccessSnippet do
end
end
- [:guest, :reporter, :maintainer, :author, :admin].each do |membership|
+ [:guest, :reporter, :maintainer, :author].each do |membership|
context membership.to_s do
let(:membership) { membership }
@@ -183,6 +183,24 @@ RSpec.describe Gitlab::GitAccessSnippet do
end
end
+ context 'admin' do
+ let(:membership) { :admin }
+
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it 'cannot perform git pushes' do
+ expect { push_access_check }.to raise_error(described_class::ForbiddenError)
+ expect { pull_access_check }.not_to raise_error
+ end
+ end
+
+ context 'when admin mode is disabled' do
+ it 'cannot perform git operations' do
+ expect { push_access_check }.to raise_error(described_class::ForbiddenError)
+ expect { pull_access_check }.to raise_error(described_class::ForbiddenError)
+ end
+ end
+ end
+
it_behaves_like 'actor is migration bot'
end
diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb
index 780f4329bcc..42b64687fc1 100644
--- a/spec/lib/gitlab/git_access_spec.rb
+++ b/spec/lib/gitlab/git_access_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::GitAccess do
include TermsHelper
include GitHelpers
+ include AdminModeHelper
let(:user) { create(:user) }
@@ -769,19 +770,39 @@ RSpec.describe Gitlab::GitAccess do
describe 'admin user' do
let(:user) { create(:admin) }
- context 'when member of the project' do
- before do
- project.add_reporter(user)
+ context 'when admin mode enabled', :enable_admin_mode do
+ context 'when member of the project' do
+ before do
+ project.add_reporter(user)
+ end
+
+ context 'pull code' do
+ it { expect { pull_access_check }.not_to raise_error }
+ end
end
- context 'pull code' do
- it { expect { pull_access_check }.not_to raise_error }
+ context 'when is not member of the project' do
+ context 'pull code' do
+ it { expect { pull_access_check }.to raise_forbidden(described_class::ERROR_MESSAGES[:download]) }
+ end
end
end
- context 'when is not member of the project' do
- context 'pull code' do
- it { expect { pull_access_check }.to raise_forbidden(described_class::ERROR_MESSAGES[:download]) }
+ context 'when admin mode disabled' do
+ context 'when member of the project' do
+ before do
+ project.add_reporter(user)
+ end
+
+ context 'pull code' do
+ it { expect { pull_access_check }.not_to raise_error }
+ end
+ end
+
+ context 'when is not member of the project' do
+ context 'pull code' do
+ it { expect { pull_access_check }.to raise_not_found }
+ end
end
end
end
@@ -870,8 +891,9 @@ RSpec.describe Gitlab::GitAccess do
# Expectations are given a custom failure message proc so that it's
# easier to identify which check(s) failed.
it "has the correct permissions for #{role}s" do
- if role == :admin
+ if [:admin_with_admin_mode, :admin_without_admin_mode].include?(role)
user.update_attribute(:admin, true)
+ enable_admin_mode!(user) if role == :admin_with_admin_mode
project.add_guest(user)
else
project.add_role(user, role)
@@ -897,7 +919,7 @@ RSpec.describe Gitlab::GitAccess do
end
permissions_matrix = {
- admin: {
+ admin_with_admin_mode: {
any: true,
push_new_branch: true,
push_master: true,
@@ -909,6 +931,18 @@ RSpec.describe Gitlab::GitAccess do
merge_into_protected_branch: true
},
+ admin_without_admin_mode: {
+ any: false,
+ push_new_branch: false,
+ push_master: false,
+ push_protected_branch: false,
+ push_remove_protected_branch: false,
+ push_tag: false,
+ push_new_tag: false,
+ push_all: false,
+ merge_into_protected_branch: false
+ },
+
maintainer: {
any: true,
push_new_branch: true,
@@ -1009,7 +1043,7 @@ RSpec.describe Gitlab::GitAccess do
run_permission_checks(permissions_matrix.deep_merge(developer: { push_protected_branch: false, push_all: false, merge_into_protected_branch: false },
maintainer: { push_protected_branch: false, push_all: false, merge_into_protected_branch: false },
- admin: { push_protected_branch: false, push_all: false, merge_into_protected_branch: false }))
+ admin_with_admin_mode: { push_protected_branch: false, push_all: false, merge_into_protected_branch: false }))
end
end
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index fba32ae0673..071a64325dc 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -87,6 +87,7 @@ label:
- merge_requests
- priorities
- epic_board_labels
+- epic_lists
milestone:
- group
- project
diff --git a/spec/lib/gitlab/search_results_spec.rb b/spec/lib/gitlab/search_results_spec.rb
index 57be9e93af2..c437b6bcceb 100644
--- a/spec/lib/gitlab/search_results_spec.rb
+++ b/spec/lib/gitlab/search_results_spec.rb
@@ -342,17 +342,36 @@ RSpec.describe Gitlab::SearchResults do
expect(results.limited_issues_count).to eq 4
end
- it 'lists all issues for admin' do
- results = described_class.new(admin, query, limit_projects)
- issues = results.objects('issues')
+ context 'with admin user' do
+ context 'when admin mode enabled', :enable_admin_mode do
+ it 'lists all issues' do
+ results = described_class.new(admin, query, limit_projects)
+ issues = results.objects('issues')
+
+ expect(issues).to include issue
+ expect(issues).to include security_issue_1
+ expect(issues).to include security_issue_2
+ expect(issues).to include security_issue_3
+ expect(issues).to include security_issue_4
+ expect(issues).not_to include security_issue_5
+ expect(results.limited_issues_count).to eq 5
+ end
+ end
- expect(issues).to include issue
- expect(issues).to include security_issue_1
- expect(issues).to include security_issue_2
- expect(issues).to include security_issue_3
- expect(issues).to include security_issue_4
- expect(issues).not_to include security_issue_5
- expect(results.limited_issues_count).to eq 5
+ context 'when admin mode disabled' do
+ it 'does not list confidential issues' do
+ results = described_class.new(admin, query, limit_projects)
+ issues = results.objects('issues')
+
+ expect(issues).to include issue
+ expect(issues).not_to include security_issue_1
+ expect(issues).not_to include security_issue_2
+ expect(issues).not_to include security_issue_3
+ expect(issues).not_to include security_issue_4
+ expect(issues).not_to include security_issue_5
+ expect(results.limited_issues_count).to eq 1
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/sidekiq_middleware/admin_mode/client_spec.rb b/spec/lib/gitlab/sidekiq_middleware/admin_mode/client_spec.rb
index 3d9ffb11ae2..3ba08455d01 100644
--- a/spec/lib/gitlab/sidekiq_middleware/admin_mode/client_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/admin_mode/client_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::SidekiqMiddleware::AdminMode::Client, :do_not_mock_admin_mode, :request_store do
+RSpec.describe Gitlab::SidekiqMiddleware::AdminMode::Client, :request_store do
include AdminModeHelper
let(:worker) do
diff --git a/spec/lib/gitlab/sidekiq_middleware/admin_mode/server_spec.rb b/spec/lib/gitlab/sidekiq_middleware/admin_mode/server_spec.rb
index 20f1e88bcf4..e8322b11875 100644
--- a/spec/lib/gitlab/sidekiq_middleware/admin_mode/server_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/admin_mode/server_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::SidekiqMiddleware::AdminMode::Server, :do_not_mock_admin_mode, :request_store do
+RSpec.describe Gitlab::SidekiqMiddleware::AdminMode::Server, :request_store do
include AdminModeHelper
let(:worker) do
diff --git a/spec/lib/gitlab/slash_commands/presenters/issue_move_spec.rb b/spec/lib/gitlab/slash_commands/presenters/issue_move_spec.rb
index df949154d4c..a4d8e3957cf 100644
--- a/spec/lib/gitlab/slash_commands/presenters/issue_move_spec.rb
+++ b/spec/lib/gitlab/slash_commands/presenters/issue_move_spec.rb
@@ -3,15 +3,20 @@
require 'spec_helper'
RSpec.describe Gitlab::SlashCommands::Presenters::IssueMove do
- let_it_be(:admin) { create(:admin) }
+ let_it_be(:user) { create(:user) }
let_it_be(:project, reload: true) { create(:project) }
let_it_be(:other_project) { create(:project) }
let_it_be(:old_issue, reload: true) { create(:issue, project: project) }
- let(:new_issue) { Issues::MoveService.new(project, admin).execute(old_issue, other_project) }
+ let(:new_issue) { Issues::MoveService.new(project, user).execute(old_issue, other_project) }
let(:attachment) { subject[:attachments].first }
subject { described_class.new(new_issue).present(old_issue) }
+ before do
+ project.add_developer(user)
+ other_project.add_developer(user)
+ end
+
it { is_expected.to be_a(Hash) }
it 'shows the new issue' do
diff --git a/spec/lib/gitlab/user_access_spec.rb b/spec/lib/gitlab/user_access_spec.rb
index 748a8336a25..97fff030906 100644
--- a/spec/lib/gitlab/user_access_spec.rb
+++ b/spec/lib/gitlab/user_access_spec.rb
@@ -45,10 +45,20 @@ RSpec.describe Gitlab::UserAccess do
let(:empty_project) { create(:project_empty_repo) }
let(:project_access) { described_class.new(user, container: empty_project) }
- it 'returns true for admins' do
- user.update!(admin: true)
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it 'returns true for admins' do
+ user.update!(admin: true)
- expect(access.can_push_to_branch?('master')).to be_truthy
+ expect(access.can_push_to_branch?('master')).to be_truthy
+ end
+ end
+
+ context 'when admin mode is disabled' do
+ it 'returns false for admins' do
+ user.update!(admin: true)
+
+ expect(access.can_push_to_branch?('master')).to be_falsey
+ end
end
it 'returns true if user is maintainer' do
@@ -85,10 +95,20 @@ RSpec.describe Gitlab::UserAccess do
let(:branch) { create :protected_branch, project: project, name: "test" }
let(:not_existing_branch) { create :protected_branch, :developers_can_merge, project: project }
- it 'returns true for admins' do
- user.update!(admin: true)
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it 'returns true for admins' do
+ user.update!(admin: true)
- expect(access.can_push_to_branch?(branch.name)).to be_truthy
+ expect(access.can_push_to_branch?(branch.name)).to be_truthy
+ end
+ end
+
+ context 'when admin mode is disabled' do
+ it 'returns false for admins' do
+ user.update!(admin: true)
+
+ expect(access.can_push_to_branch?(branch.name)).to be_falsey
+ end
end
it 'returns true if user is a maintainer' do
diff --git a/spec/lib/gitlab/visibility_level_spec.rb b/spec/lib/gitlab/visibility_level_spec.rb
index 2ac343cd1e7..ff3057d4b36 100644
--- a/spec/lib/gitlab/visibility_level_spec.rb
+++ b/spec/lib/gitlab/visibility_level_spec.rb
@@ -22,13 +22,25 @@ RSpec.describe Gitlab::VisibilityLevel do
end
describe '.levels_for_user' do
- it 'returns all levels for an admin' do
- user = build(:user, :admin)
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it 'returns all levels for an admin' do
+ user = build(:user, :admin)
+
+ expect(described_class.levels_for_user(user))
+ .to eq([Gitlab::VisibilityLevel::PRIVATE,
+ Gitlab::VisibilityLevel::INTERNAL,
+ Gitlab::VisibilityLevel::PUBLIC])
+ end
+ end
- expect(described_class.levels_for_user(user))
- .to eq([Gitlab::VisibilityLevel::PRIVATE,
- Gitlab::VisibilityLevel::INTERNAL,
- Gitlab::VisibilityLevel::PUBLIC])
+ context 'when admin mode is disabled' do
+ it 'returns INTERNAL and PUBLIC for an admin' do
+ user = build(:user, :admin)
+
+ expect(described_class.levels_for_user(user))
+ .to eq([Gitlab::VisibilityLevel::INTERNAL,
+ Gitlab::VisibilityLevel::PUBLIC])
+ end
end
it 'returns INTERNAL and PUBLIC for internal users' do
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 431a60a11a5..1b0f6b2322c 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -3555,112 +3555,6 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
end
- describe '#mergeable_with_quick_action?' do
- def create_pipeline(status)
- pipeline = create(:ci_pipeline,
- project: project,
- ref: merge_request.source_branch,
- sha: merge_request.diff_head_sha,
- status: status,
- head_pipeline_of: merge_request)
-
- pipeline
- end
-
- let_it_be(:project) { create(:project, :public, :repository, only_allow_merge_if_pipeline_succeeds: true) }
-
- let(:developer) { create(:user) }
- let(:user) { create(:user) }
- let(:merge_request) { create(:merge_request, source_project: project) }
- let(:mr_sha) { merge_request.diff_head_sha }
-
- before do
- project.add_developer(developer)
- end
-
- context 'when autocomplete_precheck is set to true' do
- it 'is mergeable by developer' do
- expect(merge_request.mergeable_with_quick_action?(developer, autocomplete_precheck: true)).to be_truthy
- end
-
- it 'is not mergeable by normal user' do
- expect(merge_request.mergeable_with_quick_action?(user, autocomplete_precheck: true)).to be_falsey
- end
- end
-
- context 'when autocomplete_precheck is set to false' do
- it 'is mergeable by developer' do
- expect(merge_request.mergeable_with_quick_action?(developer, last_diff_sha: mr_sha)).to be_truthy
- end
-
- it 'is not mergeable by normal user' do
- expect(merge_request.mergeable_with_quick_action?(user, last_diff_sha: mr_sha)).to be_falsey
- end
-
- context 'closed MR' do
- before do
- merge_request.update_attribute(:state_id, described_class.available_states[:closed])
- end
-
- it 'is not mergeable' do
- expect(merge_request.mergeable_with_quick_action?(developer, last_diff_sha: mr_sha)).to be_falsey
- end
- end
-
- context 'MR with WIP' do
- before do
- merge_request.update_attribute(:title, 'WIP: some MR')
- end
-
- it 'is not mergeable' do
- expect(merge_request.mergeable_with_quick_action?(developer, last_diff_sha: mr_sha)).to be_falsey
- end
- end
-
- context 'sha differs from the MR diff_head_sha' do
- it 'is not mergeable' do
- expect(merge_request.mergeable_with_quick_action?(developer, last_diff_sha: 'some other sha')).to be_falsey
- end
- end
-
- context 'sha is not provided' do
- it 'is not mergeable' do
- expect(merge_request.mergeable_with_quick_action?(developer)).to be_falsey
- end
- end
-
- context 'with pipeline ok' do
- before do
- create_pipeline(:success)
- end
-
- it 'is mergeable' do
- expect(merge_request.mergeable_with_quick_action?(developer, last_diff_sha: mr_sha)).to be_truthy
- end
- end
-
- context 'with failing pipeline' do
- before do
- create_pipeline(:failed)
- end
-
- it 'is not mergeable' do
- expect(merge_request.mergeable_with_quick_action?(developer, last_diff_sha: mr_sha)).to be_falsey
- end
- end
-
- context 'with running pipeline' do
- before do
- create_pipeline(:running)
- end
-
- it 'is mergeable' do
- expect(merge_request.mergeable_with_quick_action?(developer, last_diff_sha: mr_sha)).to be_truthy
- end
- end
- end
- end
-
describe '#pipeline_coverage_delta' do
let!(:merge_request) { create(:merge_request) }
diff --git a/spec/services/issuable/bulk_update_service_spec.rb b/spec/services/issuable/bulk_update_service_spec.rb
index f2bc4f717af..79543fe9f5d 100644
--- a/spec/services/issuable/bulk_update_service_spec.rb
+++ b/spec/services/issuable/bulk_update_service_spec.rb
@@ -3,8 +3,8 @@
require 'spec_helper'
RSpec.describe Issuable::BulkUpdateService do
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository, namespace: user.namespace) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :repository, namespace: user.namespace) }
def bulk_update(issuables, extra_params = {})
bulk_update_params = extra_params
@@ -31,6 +31,23 @@ RSpec.describe Issuable::BulkUpdateService do
end
end
+ shared_examples 'updates iterations' do
+ it 'succeeds' do
+ result = bulk_update(issuables, sprint_id: iteration.id)
+
+ expect(result.success?).to be_truthy
+ expect(result.payload[:count]).to eq(issuables.count)
+ end
+
+ it 'updates the issuables iteration' do
+ bulk_update(issuables, sprint_id: iteration.id)
+
+ issuables.each do |issuable|
+ expect(issuable.reload.iteration).to eq(iteration)
+ end
+ end
+ end
+
shared_examples 'updating labels' do
def create_issue_with_labels(labels)
create(:labeled_issue, project: project, labels: labels)
@@ -233,6 +250,21 @@ RSpec.describe Issuable::BulkUpdateService do
it_behaves_like 'updates milestones'
end
+ describe 'updating iterations' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+ let_it_be(:issuables) { [create(:issue, project: project)] }
+ let_it_be(:iteration) { create(:iteration, group: group) }
+
+ let(:parent) { project }
+
+ before do
+ group.add_reporter(user)
+ end
+
+ it_behaves_like 'updates iterations'
+ end
+
describe 'updating labels' do
let(:bug) { create(:label, project: project) }
let(:regression) { create(:label, project: project) }
@@ -283,7 +315,7 @@ RSpec.describe Issuable::BulkUpdateService do
end
context 'with issuables at a group level' do
- let(:group) { create(:group) }
+ let_it_be(:group) { create(:group) }
let(:parent) { group }
before do
@@ -315,6 +347,19 @@ RSpec.describe Issuable::BulkUpdateService do
end
end
+ describe 'updating iterations' do
+ let_it_be(:iteration) { create(:iteration, group: group) }
+ let_it_be(:project) { create(:project, :repository, group: group) }
+
+ context 'when issues' do
+ let_it_be(:issue1) { create(:issue, project: project) }
+ let_it_be(:issue2) { create(:issue, project: project) }
+ let_it_be(:issuables) { [issue1, issue2] }
+
+ it_behaves_like 'updates iterations'
+ end
+ end
+
describe 'updating labels' do
let(:project) { create(:project, :repository, group: group) }
let(:bug) { create(:group_label, group: group) }
diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb
index ed8872b71f7..be802c430ff 100644
--- a/spec/services/merge_requests/update_service_spec.rb
+++ b/spec/services/merge_requests/update_service_spec.rb
@@ -431,14 +431,6 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
describe 'merge' do
it_behaves_like 'correct merge behavior'
-
- context 'when merge_orchestration_service feature flag is disabled' do
- before do
- stub_feature_flags(merge_orchestration_service: false)
- end
-
- it_behaves_like 'correct merge behavior'
- end
end
context 'todos' do
diff --git a/spec/services/snippets/update_repository_storage_service_spec.rb b/spec/services/snippets/update_repository_storage_service_spec.rb
new file mode 100644
index 00000000000..b2bcd620d76
--- /dev/null
+++ b/spec/services/snippets/update_repository_storage_service_spec.rb
@@ -0,0 +1,137 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Snippets::UpdateRepositoryStorageService do
+ include Gitlab::ShellAdapter
+
+ subject { described_class.new(repository_storage_move) }
+
+ describe "#execute" do
+ let_it_be_with_reload(:snippet) { create(:snippet, :repository) }
+ let_it_be(:destination) { 'test_second_storage' }
+ let_it_be(:checksum) { snippet.repository.checksum }
+
+ let(:repository_storage_move_state) { :scheduled }
+ let(:repository_storage_move) { create(:snippet_repository_storage_move, repository_storage_move_state, container: snippet, destination_storage_name: destination) }
+ let(:snippet_repository_double) { double(:repository) }
+ let(:original_snippet_repository_double) { double(:repository) }
+
+ before do
+ allow(Gitlab.config.repositories.storages).to receive(:keys).and_return(%w[default test_second_storage])
+ allow(Gitlab::GitalyClient).to receive(:filesystem_id).with('default').and_call_original
+ allow(Gitlab::GitalyClient).to receive(:filesystem_id).with(destination).and_return(SecureRandom.uuid)
+ allow(Gitlab::Git::Repository).to receive(:new).and_call_original
+ allow(Gitlab::Git::Repository).to receive(:new)
+ .with(destination, snippet.repository.raw.relative_path, snippet.repository.gl_repository, snippet.repository.full_path)
+ .and_return(snippet_repository_double)
+ allow(Gitlab::Git::Repository).to receive(:new)
+ .with('default', snippet.repository.raw.relative_path, nil, nil)
+ .and_return(original_snippet_repository_double)
+ end
+
+ context 'when the move succeeds' do
+ it 'moves the repository to the new storage and unmarks the repository as read only' do
+ old_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
+ snippet.repository.path_to_repo
+ end
+
+ expect(snippet_repository_double).to receive(:replicate)
+ .with(snippet.repository.raw)
+ expect(snippet_repository_double).to receive(:checksum)
+ .and_return(checksum)
+ expect(original_snippet_repository_double).to receive(:remove)
+
+ result = subject.execute
+ snippet.reload
+
+ expect(result).to be_success
+ expect(snippet).not_to be_repository_read_only
+ expect(snippet.repository_storage).to eq(destination)
+ expect(gitlab_shell.repository_exists?('default', old_path)).to be(false)
+ expect(snippet.snippet_repository.shard_name).to eq(destination)
+ end
+ end
+
+ context 'when the filesystems are the same' do
+ let(:destination) { snippet.repository_storage }
+
+ it 'bails out and does nothing' do
+ result = subject.execute
+
+ expect(result).to be_error
+ expect(result.message).to match(/SameFilesystemError/)
+ end
+ end
+
+ context 'when the move fails' do
+ it 'unmarks the repository as read-only without updating the repository storage' do
+ expect(snippet_repository_double).to receive(:replicate)
+ .with(snippet.repository.raw)
+ .and_raise(Gitlab::Git::CommandError)
+
+ result = subject.execute
+
+ expect(result).to be_error
+ expect(snippet).not_to be_repository_read_only
+ expect(snippet.repository_storage).to eq('default')
+ expect(repository_storage_move).to be_failed
+ end
+ end
+
+ context 'when the cleanup fails' do
+ it 'sets the correct state' do
+ expect(snippet_repository_double).to receive(:replicate)
+ .with(snippet.repository.raw)
+ expect(snippet_repository_double).to receive(:checksum)
+ .and_return(checksum)
+ expect(original_snippet_repository_double).to receive(:remove)
+ .and_raise(Gitlab::Git::CommandError)
+
+ result = subject.execute
+
+ expect(result).to be_error
+ expect(repository_storage_move).to be_cleanup_failed
+ end
+ end
+
+ context 'when the checksum does not match' do
+ it 'unmarks the repository as read-only without updating the repository storage' do
+ expect(snippet_repository_double).to receive(:replicate)
+ .with(snippet.repository.raw)
+ expect(snippet_repository_double).to receive(:checksum)
+ .and_return('not matching checksum')
+
+ result = subject.execute
+
+ expect(result).to be_error
+ expect(snippet).not_to be_repository_read_only
+ expect(snippet.repository_storage).to eq('default')
+ end
+ end
+
+ context 'when the repository move is finished' do
+ let(:repository_storage_move_state) { :finished }
+
+ it 'is idempotent' do
+ expect do
+ result = subject.execute
+
+ expect(result).to be_success
+ end.not_to change(repository_storage_move, :state)
+ end
+ end
+
+ context 'when the repository move is failed' do
+ let(:repository_storage_move_state) { :failed }
+
+ it 'is idempotent' do
+ expect do
+ result = subject.execute
+
+ expect(result).to be_success
+ end.not_to change(repository_storage_move, :state)
+ end
+ end
+ end
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index c19c26f9a0b..e88cad93e9c 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -290,14 +290,11 @@ RSpec.configure do |config|
admin_mode_mock_dirs = %w(
./ee/spec/elastic_integration
./ee/spec/finders
- ./ee/spec/lib
./ee/spec/serializers
./ee/spec/support/shared_examples/finders/geo
./ee/spec/support/shared_examples/graphql/geo
./spec/finders
- ./spec/lib
./spec/serializers
- ./spec/support/shared_examples/lib/gitlab
./spec/workers
)
diff --git a/spec/support/helpers/stub_experiments.rb b/spec/support/helpers/stub_experiments.rb
index 9188bc704c1..247692d83ee 100644
--- a/spec/support/helpers/stub_experiments.rb
+++ b/spec/support/helpers/stub_experiments.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
module StubExperiments
- SUFFIX = Gitlab::Experimentation::Experiment::FEATURE_FLAG_SUFFIX
-
# Stub Experiment with `key: true/false`
#
# @param [Hash] experiment where key is feature name and value is boolean whether active or not.
@@ -13,7 +11,6 @@ module StubExperiments
allow(Gitlab::Experimentation).to receive(:active?).and_call_original
experiments.each do |experiment_key, enabled|
- Feature.persist_used!("#{experiment_key}#{SUFFIX}")
allow(Gitlab::Experimentation).to receive(:active?).with(experiment_key) { enabled }
end
end
@@ -28,7 +25,6 @@ module StubExperiments
allow(Gitlab::Experimentation).to receive(:in_experiment_group?).and_call_original
experiments.each do |experiment_key, enabled|
- Feature.persist_used!("#{experiment_key}#{SUFFIX}")
allow(Gitlab::Experimentation).to receive(:in_experiment_group?).with(experiment_key, anything) { enabled }
end
end
diff --git a/spec/support/shared_examples/lib/gitlab/project_search_results_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/project_search_results_shared_examples.rb
index 94ef41ce5a5..f83fecee4ea 100644
--- a/spec/support/shared_examples/lib/gitlab/project_search_results_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/project_search_results_shared_examples.rb
@@ -54,7 +54,7 @@ RSpec.shared_examples 'access restricted confidential issues' do
end
end
- context 'when the user is a developper' do
+ context 'when the user is a developer' do
let(:user) do
create(:user) { |user| project.add_developer(user) }
end
@@ -70,10 +70,19 @@ RSpec.shared_examples 'access restricted confidential issues' do
context 'when the user is admin', :request_store do
let(:user) { create(:user, admin: true) }
- it 'lists all project issues' do
- expect(objects).to contain_exactly(issue,
- security_issue_1,
- security_issue_2)
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it 'lists all project issues' do
+ expect(objects).to contain_exactly(issue,
+ security_issue_1,
+ security_issue_2)
+ end
+ end
+
+ context 'when admin mode is disabled' do
+ it 'does not list project confidential issues' do
+ expect(objects).to contain_exactly(issue)
+ expect(results.limited_issues_count).to eq 1
+ end
end
end
end