diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-12-17 18:10:14 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-12-17 18:10:14 +0000 |
commit | f3b791d5d5b0b058d2b717da1a54a63f3bba5adc (patch) | |
tree | 0f88def948be12834a60ca156502c304e0a10aa3 | |
parent | ef73ee020e96f39a109a16c4c6b018d8ea7cabc1 (diff) | |
download | gitlab-ce-f3b791d5d5b0b058d2b717da1a54a63f3bba5adc.tar.gz |
Add latest changes from gitlab-org/gitlab@master
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 |