From f52f8542b47c9e00ddf420abaf2263de168988f9 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Tue, 31 Oct 2023 12:11:01 +0000 Subject: Add latest changes from gitlab-org/gitlab@master --- .rubocop_todo/rspec/feature_category.yml | 1 - .rubocop_todo/style/percent_literal_delimiters.yml | 60 ----- .../filepath_form/components/template_selector.vue | 5 +- app/assets/javascripts/editor/constants.js | 5 - app/assets/javascripts/header.js | 3 + .../javascripts/ide/components/repo_editor.vue | 9 +- app/assets/javascripts/ide/lib/alerts/index.js | 3 +- .../ide/stores/modules/file_templates/getters.js | 3 +- app/assets/javascripts/issues/issue.js | 2 + app/assets/javascripts/lib/utils/common_utils.js | 15 ++ app/assets/javascripts/lib/utils/constants.js | 3 + .../pipeline_wizard/pipeline_wizard.vue | 3 +- .../components/list_selector/constants.js | 7 + .../vue_shared/components/list_selector/index.vue | 135 +++++++++++ .../vue_shared/components/list_selector/user.vue | 55 +++++ app/graphql/mutations/base_mutation.rb | 6 - app/graphql/types/base_argument.rb | 22 -- .../types/permission_types/base_permission_type.rb | 2 +- app/services/git/branch_hooks_service.rb | 1 - ...ject_id_when_npm_and_not_pending_destruction.rb | 23 ++ db/schema_migrations/20231030095419 | 1 + db/structure.sql | 2 - doc/api/graphql/reference/index.md | 268 ++++++++++----------- doc/api/scim.md | 2 +- doc/development/internal_api/index.md | 4 +- lib/api/helm_packages.rb | 2 + lib/api/helpers.rb | 2 +- lib/gitlab/ci/yaml_processor/dag.rb | 2 + lib/gitlab/internal_events.rb | 2 - .../usage_data_counters/hll_redis_counter.rb | 2 - lib/gitlab/usage_data_counters/redis_counter.rb | 4 - locale/gitlab.pot | 12 + qa/Gemfile | 2 +- qa/Gemfile.lock | 6 +- spec/frontend/fixtures/issues.rb | 2 +- spec/frontend/fixtures/snippet.rb | 2 +- spec/frontend/header_spec.js | 9 +- spec/frontend/ide/components/repo_editor_spec.js | 9 +- spec/frontend/issues/issue_spec.js | 12 +- spec/frontend/lib/utils/common_utils_spec.js | 24 ++ spec/frontend/shortcuts_spec.js | 40 +-- .../components/list_selector/index_spec.js | 134 +++++++++++ .../components/list_selector/mock_data.js | 25 ++ .../components/list_selector/user_spec.js | 55 +++++ spec/graphql/mutations/base_mutation_spec.rb | 58 ----- spec/graphql/mutations/ci/runner/delete_spec.rb | 2 +- spec/graphql/mutations/ci/runner/update_spec.rb | 2 +- .../mutations/merge_requests/update_spec.rb | 14 -- spec/graphql/types/base_argument_spec.rb | 39 +-- spec/lib/gitlab/ci/yaml_processor/dag_spec.rb | 12 +- spec/lib/gitlab/ci/yaml_processor_spec.rb | 17 ++ .../usage_data_counters/hll_redis_counter_spec.rb | 88 +++---- .../usage_data_counters/redis_counter_spec.rb | 48 +--- spec/metrics_server/metrics_server_spec.rb | 4 +- .../alert_management/http_integration_spec.rb | 6 +- spec/models/appearance_spec.rb | 2 +- spec/models/application_setting_spec.rb | 8 +- spec/models/authentication_event_spec.rb | 4 +- spec/models/blob_viewer/base_spec.rb | 4 +- spec/models/ci/build_dependencies_spec.rb | 6 +- spec/models/ci/build_spec.rb | 38 +-- spec/models/ci/job_artifact_spec.rb | 2 +- spec/models/ci/pipeline_spec.rb | 4 +- spec/models/ci/runner_spec.rb | 2 +- spec/models/clusters/agent_spec.rb | 2 +- spec/models/clusters/platforms/kubernetes_spec.rb | 2 +- spec/models/commit_range_spec.rb | 2 +- spec/models/commit_spec.rb | 4 +- spec/models/commit_status_spec.rb | 2 +- spec/models/compare_spec.rb | 4 +- spec/models/concerns/awardable_spec.rb | 8 +- spec/models/concerns/case_sensitivity_spec.rb | 6 +- spec/models/concerns/featurable_spec.rb | 2 +- spec/models/concerns/ignorable_columns_spec.rb | 4 +- spec/models/concerns/issuable_spec.rb | 4 +- .../concerns/pg_full_text_searchable_spec.rb | 4 +- .../project_features_compatibility_spec.rb | 6 +- spec/models/concerns/reactive_caching_spec.rb | 4 +- spec/models/concerns/sortable_spec.rb | 22 +- spec/models/deployment_spec.rb | 10 +- spec/models/diff_viewer/base_spec.rb | 4 +- spec/models/environment_spec.rb | 10 +- spec/models/group_label_spec.rb | 2 +- spec/models/instance_configuration_spec.rb | 4 +- spec/models/integration_spec.rb | 2 +- spec/models/integrations/buildkite_spec.rb | 2 +- spec/models/integrations/campfire_spec.rb | 2 +- spec/models/integrations/jira_spec.rb | 12 +- spec/models/integrations/teamcity_spec.rb | 4 +- spec/models/issue_spec.rb | 8 +- spec/models/merge_request_diff_spec.rb | 2 +- spec/models/namespace_statistics_spec.rb | 2 +- spec/models/packages/package_spec.rb | 2 +- spec/models/packages/tag_spec.rb | 2 +- spec/models/pages_domain_spec.rb | 18 +- spec/models/personal_access_token_spec.rb | 2 +- spec/models/project_feature_spec.rb | 4 +- spec/models/project_label_spec.rb | 2 +- spec/models/project_spec.rb | 14 +- spec/models/projects/topic_spec.rb | 2 +- spec/models/prometheus_metric_spec.rb | 20 +- spec/models/releases/link_spec.rb | 2 +- spec/models/repository_spec.rb | 32 +-- spec/models/snippet_spec.rb | 2 +- spec/models/terraform/state_spec.rb | 2 +- spec/models/user_spec.rb | 16 +- spec/models/web_ide_terminal_spec.rb | 6 +- spec/models/zoom_meeting_spec.rb | 4 +- spec/policies/project_policy_spec.rb | 44 ++-- .../code_coverage_presenter_spec.rb | 8 +- .../code_quality_mr_diff_presenter_spec.rb | 8 +- .../nuget/packages_metadata_presenter_spec.rb | 2 +- .../nuget/search_results_presenter_spec.rb | 2 +- .../graphql/mutations/issues/set_due_date_spec.rb | 2 +- .../mutations/merge_requests/update_spec.rb | 12 + spec/requests/api/helm_packages_spec.rb | 6 + spec/requests/api/projects_spec.rb | 18 +- spec/services/ci/play_build_service_spec.rb | 4 - spec/services/git/branch_hooks_service_spec.rb | 21 +- .../helpers/packages_manager_api_spec_helper.rb | 34 --- .../helpers/packages_manager_api_spec_helpers.rb | 34 +++ spec/support/rspec_order_todo.yml | 1 - .../requests/api/helm_packages_shared_examples.rb | 10 +- workhorse/internal/goredis/goredis.go | 28 ++- workhorse/internal/goredis/goredis_test.go | 55 +++++ 125 files changed, 1144 insertions(+), 761 deletions(-) create mode 100644 app/assets/javascripts/vue_shared/components/list_selector/constants.js create mode 100644 app/assets/javascripts/vue_shared/components/list_selector/index.vue create mode 100644 app/assets/javascripts/vue_shared/components/list_selector/user.vue create mode 100644 db/post_migrate/20231030095419_remove_temp_index_to_packages_on_project_id_when_npm_and_not_pending_destruction.rb create mode 100644 db/schema_migrations/20231030095419 create mode 100644 spec/frontend/vue_shared/components/list_selector/index_spec.js create mode 100644 spec/frontend/vue_shared/components/list_selector/mock_data.js create mode 100644 spec/frontend/vue_shared/components/list_selector/user_spec.js delete mode 100644 spec/graphql/mutations/base_mutation_spec.rb delete mode 100644 spec/support/helpers/packages_manager_api_spec_helper.rb create mode 100644 spec/support/helpers/packages_manager_api_spec_helpers.rb diff --git a/.rubocop_todo/rspec/feature_category.yml b/.rubocop_todo/rspec/feature_category.yml index 8ec7a156ae9..eaa74ec4d20 100644 --- a/.rubocop_todo/rspec/feature_category.yml +++ b/.rubocop_todo/rspec/feature_category.yml @@ -1930,7 +1930,6 @@ RSpec/FeatureCategory: - 'spec/graphql/mutations/alert_management/prometheus_integration/reset_token_spec.rb' - 'spec/graphql/mutations/alert_management/prometheus_integration/update_spec.rb' - 'spec/graphql/mutations/alert_management/update_alert_status_spec.rb' - - 'spec/graphql/mutations/base_mutation_spec.rb' - 'spec/graphql/mutations/boards/issues/issue_move_list_spec.rb' - 'spec/graphql/mutations/boards/lists/create_spec.rb' - 'spec/graphql/mutations/boards/lists/update_spec.rb' diff --git a/.rubocop_todo/style/percent_literal_delimiters.yml b/.rubocop_todo/style/percent_literal_delimiters.yml index 82df5353f2c..b90c925d976 100644 --- a/.rubocop_todo/style/percent_literal_delimiters.yml +++ b/.rubocop_todo/style/percent_literal_delimiters.yml @@ -3,66 +3,6 @@ Style/PercentLiteralDelimiters: Exclude: - 'metrics_server/metrics_server.rb' - - 'spec/metrics_server/metrics_server_spec.rb' - - 'spec/models/alert_management/http_integration_spec.rb' - - 'spec/models/appearance_spec.rb' - - 'spec/models/application_setting_spec.rb' - - 'spec/models/authentication_event_spec.rb' - - 'spec/models/blob_viewer/base_spec.rb' - - 'spec/models/ci/build_dependencies_spec.rb' - - 'spec/models/ci/build_spec.rb' - - 'spec/models/ci/job_artifact_spec.rb' - - 'spec/models/ci/pipeline_spec.rb' - - 'spec/models/ci/runner_spec.rb' - - 'spec/models/clusters/agent_spec.rb' - - 'spec/models/clusters/platforms/kubernetes_spec.rb' - - 'spec/models/commit_range_spec.rb' - - 'spec/models/commit_spec.rb' - - 'spec/models/commit_status_spec.rb' - - 'spec/models/compare_spec.rb' - - 'spec/models/concerns/awardable_spec.rb' - - 'spec/models/concerns/case_sensitivity_spec.rb' - - 'spec/models/concerns/featurable_spec.rb' - - 'spec/models/concerns/ignorable_columns_spec.rb' - - 'spec/models/concerns/issuable_spec.rb' - - 'spec/models/concerns/pg_full_text_searchable_spec.rb' - - 'spec/models/concerns/project_features_compatibility_spec.rb' - - 'spec/models/concerns/reactive_caching_spec.rb' - - 'spec/models/concerns/sortable_spec.rb' - - 'spec/models/deployment_spec.rb' - - 'spec/models/diff_viewer/base_spec.rb' - - 'spec/models/environment_spec.rb' - - 'spec/models/group_label_spec.rb' - - 'spec/models/instance_configuration_spec.rb' - - 'spec/models/integration_spec.rb' - - 'spec/models/integrations/buildkite_spec.rb' - - 'spec/models/integrations/campfire_spec.rb' - - 'spec/models/integrations/jira_spec.rb' - - 'spec/models/integrations/teamcity_spec.rb' - - 'spec/models/issue_spec.rb' - - 'spec/models/merge_request_diff_spec.rb' - - 'spec/models/namespace_statistics_spec.rb' - - 'spec/models/packages/package_spec.rb' - - 'spec/models/packages/tag_spec.rb' - - 'spec/models/pages_domain_spec.rb' - - 'spec/models/personal_access_token_spec.rb' - - 'spec/models/project_feature_spec.rb' - - 'spec/models/project_label_spec.rb' - - 'spec/models/project_spec.rb' - - 'spec/models/projects/topic_spec.rb' - - 'spec/models/prometheus_metric_spec.rb' - - 'spec/models/releases/link_spec.rb' - - 'spec/models/repository_spec.rb' - - 'spec/models/snippet_spec.rb' - - 'spec/models/terraform/state_spec.rb' - - 'spec/models/user_spec.rb' - - 'spec/models/web_ide_terminal_spec.rb' - - 'spec/models/zoom_meeting_spec.rb' - - 'spec/policies/project_policy_spec.rb' - - 'spec/presenters/ci/pipeline_artifacts/code_coverage_presenter_spec.rb' - - 'spec/presenters/ci/pipeline_artifacts/code_quality_mr_diff_presenter_spec.rb' - - 'spec/presenters/packages/nuget/packages_metadata_presenter_spec.rb' - - 'spec/presenters/packages/nuget/search_results_presenter_spec.rb' - 'spec/requests/api/badges_spec.rb' - 'spec/requests/api/ci/jobs_spec.rb' - 'spec/requests/api/ci/pipelines_spec.rb' diff --git a/app/assets/javascripts/blob/filepath_form/components/template_selector.vue b/app/assets/javascripts/blob/filepath_form/components/template_selector.vue index 51c69590796..379d5e38197 100644 --- a/app/assets/javascripts/blob/filepath_form/components/template_selector.vue +++ b/app/assets/javascripts/blob/filepath_form/components/template_selector.vue @@ -2,6 +2,7 @@ import { GlCollapsibleListbox } from '@gitlab/ui'; import SuggestGitlabCiYml from '~/blob/suggest_gitlab_ci_yml/components/popover.vue'; import { __ } from '~/locale'; +import { DEFAULT_CI_CONFIG_PATH, CI_CONFIG_PATH_EXTENSION } from '~/lib/utils/constants'; const templateSelectors = [ { @@ -12,8 +13,8 @@ const templateSelectors = [ }, { key: 'gitlab_ci_ymls', - name: '.gitlab-ci.yml', - pattern: /(.gitlab-ci.yml)/, + name: DEFAULT_CI_CONFIG_PATH, + pattern: CI_CONFIG_PATH_EXTENSION, type: 'gitlab_ci_ymls', }, { diff --git a/app/assets/javascripts/editor/constants.js b/app/assets/javascripts/editor/constants.js index 2be671ec7d8..2d50b7e4319 100644 --- a/app/assets/javascripts/editor/constants.js +++ b/app/assets/javascripts/editor/constants.js @@ -53,11 +53,6 @@ export const EDITOR_EXTENSION_STORE_IS_MISSING_ERROR = s__( export const EXTENSION_BASE_LINE_LINK_ANCHOR_CLASS = 'link-anchor'; export const EXTENSION_BASE_LINE_NUMBERS_CLASS = 'line-numbers'; -// For CI config schemas the filename must match -// '*.gitlab-ci.yml' regardless of project configuration. -// https://gitlab.com/gitlab-org/gitlab/-/issues/293641 -export const EXTENSION_CI_SCHEMA_FILE_NAME_MATCH = '.gitlab-ci.yml'; - export const EXTENSION_MARKDOWN_PREVIEW_PANEL_CLASS = 'md'; export const EXTENSION_MARKDOWN_PREVIEW_PANEL_PARENT_CLASS = 'source-editor-preview'; export const EXTENSION_MARKDOWN_PREVIEW_ACTION_ID = 'markdown-preview'; diff --git a/app/assets/javascripts/header.js b/app/assets/javascripts/header.js index 25a84d17379..095a2dc1324 100644 --- a/app/assets/javascripts/header.js +++ b/app/assets/javascripts/header.js @@ -1,3 +1,6 @@ +// TODO: Remove this with the removal of the old navigation. +// See https://gitlab.com/groups/gitlab-org/-/epics/11875. + import Vue from 'vue'; import NewNavToggle from '~/nav/components/new_nav_toggle.vue'; import { highCountTrim } from '~/lib/utils/text_utility'; diff --git a/app/assets/javascripts/ide/components/repo_editor.vue b/app/assets/javascripts/ide/components/repo_editor.vue index 137df9aa102..3b59fe86764 100644 --- a/app/assets/javascripts/ide/components/repo_editor.vue +++ b/app/assets/javascripts/ide/components/repo_editor.vue @@ -8,7 +8,6 @@ import { EDITOR_TYPE_CODE, EDITOR_CODE_INSTANCE_FN, EDITOR_DIFF_INSTANCE_FN, - EXTENSION_CI_SCHEMA_FILE_NAME_MATCH, } from '~/editor/constants'; import { SourceEditorExtension } from '~/editor/extensions/source_editor_extension_base'; import { EditorWebIdeExtension } from '~/editor/extensions/source_editor_webide_ext'; @@ -30,6 +29,7 @@ import { viewerInformationForPath } from '~/vue_shared/components/content_viewer import DiffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue'; import { markRaw } from '~/lib/utils/vue3compat/mark_raw'; import { readFileAsDataURL } from '~/lib/utils/file_utility'; +import { isDefaultCiConfig, hasCiConfigExtension } from '~/lib/utils/common_utils'; import { leftSidebarViews, @@ -152,8 +152,9 @@ export default { }, isCiConfigFile() { return ( - this.file.path === EXTENSION_CI_SCHEMA_FILE_NAME_MATCH && - this.editor?.getEditorType() === EDITOR_TYPE_CODE + // For CI config schemas the filename must match '*.gitlab-ci.yml' regardless of project configuration. + // https://gitlab.com/gitlab-org/gitlab/-/issues/293641 + hasCiConfigExtension(this.file.path) && this.editor?.getEditorType() === EDITOR_TYPE_CODE ); }, }, @@ -162,7 +163,7 @@ export default { handler() { this.stopWatchingCiYaml(); - if (this.file.name === '.gitlab-ci.yml') { + if (isDefaultCiConfig(this.file.name)) { this.startWatchingCiYaml(); } }, diff --git a/app/assets/javascripts/ide/lib/alerts/index.js b/app/assets/javascripts/ide/lib/alerts/index.js index c9db9779b1f..ac4eeb0386f 100644 --- a/app/assets/javascripts/ide/lib/alerts/index.js +++ b/app/assets/javascripts/ide/lib/alerts/index.js @@ -1,3 +1,4 @@ +import { isDefaultCiConfig } from '~/lib/utils/common_utils'; import { leftSidebarViews } from '../../constants'; import EnvironmentsMessage from './environments.vue'; @@ -6,7 +7,7 @@ const alerts = [ key: Symbol('ALERT_ENVIRONMENT'), show: (state, file) => state.currentActivityView === leftSidebarViews.commit.name && - file.path === '.gitlab-ci.yml' && + isDefaultCiConfig(file.path) && state.environmentsGuidanceAlertDetected && !state.environmentsGuidanceAlertDismissed, props: { variant: 'tip' }, diff --git a/app/assets/javascripts/ide/stores/modules/file_templates/getters.js b/app/assets/javascripts/ide/stores/modules/file_templates/getters.js index bf0d3ed337c..5681f6cdec5 100644 --- a/app/assets/javascripts/ide/stores/modules/file_templates/getters.js +++ b/app/assets/javascripts/ide/stores/modules/file_templates/getters.js @@ -1,9 +1,10 @@ import { __ } from '~/locale'; +import { DEFAULT_CI_CONFIG_PATH } from '~/lib/utils/constants'; import { leftSidebarViews } from '../../../constants'; export const templateTypes = () => [ { - name: '.gitlab-ci.yml', + name: DEFAULT_CI_CONFIG_PATH, key: 'gitlab_ci_ymls', }, { diff --git a/app/assets/javascripts/issues/issue.js b/app/assets/javascripts/issues/issue.js index 06bbcdc12ea..b83db65caa6 100644 --- a/app/assets/javascripts/issues/issue.js +++ b/app/assets/javascripts/issues/issue.js @@ -53,6 +53,8 @@ export default class Issue { $(document).trigger('issuable:change', isClosed); + // TODO: Remove this with the removal of the old navigation. + // See https://gitlab.com/groups/gitlab-org/-/epics/11875. let numProjectIssues = Number( projectIssuesCounter.first().text().trim().replace(/[^\d]/, ''), ); diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js index 7d16af003e4..27da2ac6ce1 100644 --- a/app/assets/javascripts/lib/utils/common_utils.js +++ b/app/assets/javascripts/lib/utils/common_utils.js @@ -7,6 +7,7 @@ import $ from 'jquery'; import { isFunction, defer, escape, partial, toLower } from 'lodash'; import Cookies from '~/lib/utils/cookies'; import { SCOPED_LABEL_DELIMITER } from '~/sidebar/components/labels/labels_select_widget/constants'; +import { DEFAULT_CI_CONFIG_PATH, CI_CONFIG_PATH_EXTENSION } from '~/lib/utils/constants'; import { convertToCamelCase, convertToSnakeCase } from './text_utility'; import { isObject } from './type_utility'; import { getLocationHash } from './url_utility'; @@ -737,3 +738,17 @@ export const isCurrentUser = (userId) => { export const cloneWithoutReferences = (obj) => { return JSON.parse(JSON.stringify(obj)); }; + +/** + * Returns true if the given path is the default CI config path. + */ +export const isDefaultCiConfig = (path) => { + return path === DEFAULT_CI_CONFIG_PATH; +}; + +/** + * Returns true if the given path has the CI config path extension. + */ +export const hasCiConfigExtension = (path) => { + return CI_CONFIG_PATH_EXTENSION.test(path); +}; diff --git a/app/assets/javascripts/lib/utils/constants.js b/app/assets/javascripts/lib/utils/constants.js index da5fb831ae5..d9ac0abf7b3 100644 --- a/app/assets/javascripts/lib/utils/constants.js +++ b/app/assets/javascripts/lib/utils/constants.js @@ -23,3 +23,6 @@ export const BYTES_FORMAT_BYTES = 'B'; export const BYTES_FORMAT_KIB = 'KiB'; export const BYTES_FORMAT_MIB = 'MiB'; export const BYTES_FORMAT_GIB = 'GiB'; + +export const DEFAULT_CI_CONFIG_PATH = '.gitlab-ci.yml'; +export const CI_CONFIG_PATH_EXTENSION = /(\.gitlab-ci\.yml)/; diff --git a/app/assets/javascripts/pipeline_wizard/pipeline_wizard.vue b/app/assets/javascripts/pipeline_wizard/pipeline_wizard.vue index 5a93de3b1be..3676ba96254 100644 --- a/app/assets/javascripts/pipeline_wizard/pipeline_wizard.vue +++ b/app/assets/javascripts/pipeline_wizard/pipeline_wizard.vue @@ -1,5 +1,6 @@ + + diff --git a/app/assets/javascripts/vue_shared/components/list_selector/user.vue b/app/assets/javascripts/vue_shared/components/list_selector/user.vue new file mode 100644 index 00000000000..fdbc767db81 --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/list_selector/user.vue @@ -0,0 +1,55 @@ + + + diff --git a/app/graphql/mutations/base_mutation.rb b/app/graphql/mutations/base_mutation.rb index 994668b5f8f..8419f7d5eae 100644 --- a/app/graphql/mutations/base_mutation.rb +++ b/app/graphql/mutations/base_mutation.rb @@ -30,12 +30,6 @@ module Mutations def ready?(**args) raise_resource_not_available_error!(ERROR_MESSAGE) if read_only? - missing_args = self.class.arguments.values - .reject { |arg| arg.accepts?(args.fetch(arg.keyword, :not_given)) } - .map(&:graphql_name) - - raise ArgumentError, "Arguments must be provided: #{missing_args.join(", ")}" if missing_args.any? - true end diff --git a/app/graphql/types/base_argument.rb b/app/graphql/types/base_argument.rb index cda7fa4a5df..3b4223c3ba1 100644 --- a/app/graphql/types/base_argument.rb +++ b/app/graphql/types/base_argument.rb @@ -9,29 +9,7 @@ module Types def initialize(*args, **kwargs, &block) @doc_reference = kwargs.delete(:see) - # our custom addition `nullable` which allows us to declare - # an argument that must be provided, even if its value is null. - # When `required: true` then required arguments must not be null. - @gl_required = !!kwargs[:required] - @gl_nullable = kwargs[:required] == :nullable - - # Only valid if an argument is also required. - if @gl_nullable - # Since the framework asserts that "required" means "cannot be null" - # we have to switch off "required" but still do the check in `ready?` behind the scenes - kwargs[:required] = false - end - super(*args, **kwargs, &block) end - - def accepts?(value) - # if the argument is declared as required, it must be included - return false if @gl_required && value == :not_given - # if the argument is declared as required, the value can only be null IF it is also nullable. - return false if @gl_required && value.nil? && !@gl_nullable - - true - end end end diff --git a/app/graphql/types/permission_types/base_permission_type.rb b/app/graphql/types/permission_types/base_permission_type.rb index d45c61f489b..3c0e68bdaf2 100644 --- a/app/graphql/types/permission_types/base_permission_type.rb +++ b/app/graphql/types/permission_types/base_permission_type.rb @@ -21,7 +21,7 @@ module Types kword_args = kword_args.reverse_merge( name: name, type: GraphQL::Types::Boolean, - description: "Indicates the user can perform `#{name}` on this resource", + description: "If `true`, the user can perform `#{name}` on this resource", null: false) field(**kword_args, &block) # rubocop:disable Graphql/Descriptions diff --git a/app/services/git/branch_hooks_service.rb b/app/services/git/branch_hooks_service.rb index a2eb4f1f396..c6214311692 100644 --- a/app/services/git/branch_hooks_service.rb +++ b/app/services/git/branch_hooks_service.rb @@ -110,7 +110,6 @@ module Git end def track_ci_config_change_event - return unless ::ServicePing::ServicePingSettings.enabled? return unless default_branch? commits_changing_ci_config.each do |commit| diff --git a/db/post_migrate/20231030095419_remove_temp_index_to_packages_on_project_id_when_npm_and_not_pending_destruction.rb b/db/post_migrate/20231030095419_remove_temp_index_to_packages_on_project_id_when_npm_and_not_pending_destruction.rb new file mode 100644 index 00000000000..cd3fccf5f4d --- /dev/null +++ b/db/post_migrate/20231030095419_remove_temp_index_to_packages_on_project_id_when_npm_and_not_pending_destruction.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +class RemoveTempIndexToPackagesOnProjectIdWhenNpmAndNotPendingDestruction < Gitlab::Database::Migration[2.2] + disable_ddl_transaction! + milestone '16.7' + + INDEX_NAME = 'tmp_idx_packages_on_project_id_when_npm_not_pending_destruction' + NPM_PACKAGE_TYPE = 2 + PENDING_DESTRUCTION_STATUS = 4 + + def up + remove_concurrent_index_by_name :packages_packages, INDEX_NAME + end + + def down + add_concurrent_index( + :packages_packages, + :project_id, + name: INDEX_NAME, + where: "package_type = #{NPM_PACKAGE_TYPE} AND status <> #{PENDING_DESTRUCTION_STATUS}" + ) + end +end diff --git a/db/schema_migrations/20231030095419 b/db/schema_migrations/20231030095419 new file mode 100644 index 00000000000..039ad039283 --- /dev/null +++ b/db/schema_migrations/20231030095419 @@ -0,0 +1 @@ +99b845e37c091107a0540a182e4376bb0c0b0b2c46def577a96cbcf1971a8cd4 \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index bead50c1c50..c9d55842ba2 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -35040,8 +35040,6 @@ CREATE INDEX tmp_idx_orphaned_approval_merge_request_rules ON approval_merge_req CREATE INDEX tmp_idx_orphaned_approval_project_rules ON approval_project_rules USING btree (id) WHERE ((report_type = ANY (ARRAY[2, 4])) AND (security_orchestration_policy_configuration_id IS NULL)); -CREATE INDEX tmp_idx_packages_on_project_id_when_npm_not_pending_destruction ON packages_packages USING btree (project_id) WHERE ((package_type = 2) AND (status <> 4)); - CREATE INDEX tmp_index_ci_job_artifacts_on_expire_at_where_locked_unknown ON ci_job_artifacts USING btree (expire_at, job_id) WHERE ((locked = 2) AND (expire_at IS NOT NULL)); CREATE INDEX tmp_index_cis_vulnerability_reads_on_id ON vulnerability_reads USING btree (id) WHERE (report_type = 7); diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index fc43d7b2ebf..3edefe0c320 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -13204,8 +13204,8 @@ four standard [pagination arguments](#connection-pagination-arguments): | Name | Type | Description | | ---- | ---- | ----------- | -| `createNote` | [`Boolean!`](#boolean) | Indicates the user can perform `create_note` on this resource. | -| `readAbuseReport` | [`Boolean!`](#boolean) | Indicates the user can perform `read_abuse_report` on this resource. | +| `createNote` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_note` on this resource. | +| `readAbuseReport` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_abuse_report` on this resource. | ### `AccessLevel` @@ -15893,9 +15893,9 @@ A custom emoji uploaded by user. | Name | Type | Description | | ---- | ---- | ----------- | -| `createCustomEmoji` | [`Boolean!`](#boolean) | Indicates the user can perform `create_custom_emoji` on this resource. | -| `deleteCustomEmoji` | [`Boolean!`](#boolean) | Indicates the user can perform `delete_custom_emoji` on this resource. | -| `readCustomEmoji` | [`Boolean!`](#boolean) | Indicates the user can perform `read_custom_emoji` on this resource. | +| `createCustomEmoji` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_custom_emoji` on this resource. | +| `deleteCustomEmoji` | [`Boolean!`](#boolean) | If `true`, the user can perform `delete_custom_emoji` on this resource. | +| `readCustomEmoji` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_custom_emoji` on this resource. | ### `CustomerRelationsContact` @@ -16132,7 +16132,7 @@ Check permissions for the current user on site profile. | Name | Type | Description | | ---- | ---- | ----------- | -| `createOnDemandDastScan` | [`Boolean!`](#boolean) | Indicates the user can perform `create_on_demand_dast_scan` on this resource. | +| `createOnDemandDastScan` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_on_demand_dast_scan` on this resource. | ### `DastSiteValidation` @@ -16357,8 +16357,8 @@ Approval summary of the deployment. | Name | Type | Description | | ---- | ---- | ----------- | | `approveDeployment` | [`Boolean!`](#boolean) | Indicates the user can perform `approve_deployment` on this resource. This field can only be resolved for one environment in any single request. | -| `destroyDeployment` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_deployment` on this resource. | -| `updateDeployment` | [`Boolean!`](#boolean) | Indicates the user can perform `update_deployment` on this resource. | +| `destroyDeployment` | [`Boolean!`](#boolean) | If `true`, the user can perform `destroy_deployment` on this resource. | +| `updateDeployment` | [`Boolean!`](#boolean) | If `true`, the user can perform `update_deployment` on this resource. | ### `DeploymentTag` @@ -17006,9 +17006,9 @@ Returns [`Deployment`](#deployment). | Name | Type | Description | | ---- | ---- | ----------- | -| `destroyEnvironment` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_environment` on this resource. | -| `stopEnvironment` | [`Boolean!`](#boolean) | Indicates the user can perform `stop_environment` on this resource. | -| `updateEnvironment` | [`Boolean!`](#boolean) | Indicates the user can perform `update_environment` on this resource. | +| `destroyEnvironment` | [`Boolean!`](#boolean) | If `true`, the user can perform `destroy_environment` on this resource. | +| `stopEnvironment` | [`Boolean!`](#boolean) | If `true`, the user can perform `stop_environment` on this resource. | +| `updateEnvironment` | [`Boolean!`](#boolean) | If `true`, the user can perform `update_environment` on this resource. | ### `Epic` @@ -17483,14 +17483,14 @@ Check permissions for the current user on an epic. | Name | Type | Description | | ---- | ---- | ----------- | -| `adminEpic` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_epic` on this resource. | -| `awardEmoji` | [`Boolean!`](#boolean) | Indicates the user can perform `award_emoji` on this resource. | -| `createEpic` | [`Boolean!`](#boolean) | Indicates the user can perform `create_epic` on this resource. | -| `createNote` | [`Boolean!`](#boolean) | Indicates the user can perform `create_note` on this resource. | -| `destroyEpic` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_epic` on this resource. | -| `readEpic` | [`Boolean!`](#boolean) | Indicates the user can perform `read_epic` on this resource. | -| `readEpicIid` | [`Boolean!`](#boolean) | Indicates the user can perform `read_epic_iid` on this resource. | -| `updateEpic` | [`Boolean!`](#boolean) | Indicates the user can perform `update_epic` on this resource. | +| `adminEpic` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_epic` on this resource. | +| `awardEmoji` | [`Boolean!`](#boolean) | If `true`, the user can perform `award_emoji` on this resource. | +| `createEpic` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_epic` on this resource. | +| `createNote` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_note` on this resource. | +| `destroyEpic` | [`Boolean!`](#boolean) | If `true`, the user can perform `destroy_epic` on this resource. | +| `readEpic` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_epic` on this resource. | +| `readEpicIid` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_epic_iid` on this resource. | +| `updateEpic` | [`Boolean!`](#boolean) | If `true`, the user can perform `update_epic` on this resource. | ### `EscalationPolicyType` @@ -19188,9 +19188,9 @@ Returns [`UserMergeRequestInteraction`](#usermergerequestinteraction). | Name | Type | Description | | ---- | ---- | ----------- | -| `createCustomEmoji` | [`Boolean!`](#boolean) | Indicates the user can perform `create_custom_emoji` on this resource. | -| `createProjects` | [`Boolean!`](#boolean) | Indicates the user can perform `create_projects` on this resource. | -| `readGroup` | [`Boolean!`](#boolean) | Indicates the user can perform `read_group` on this resource. | +| `createCustomEmoji` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_custom_emoji` on this resource. | +| `createProjects` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_projects` on this resource. | +| `readGroup` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_group` on this resource. | ### `GroupReleaseStats` @@ -19778,15 +19778,15 @@ Check permissions for the current user on a issue. | Name | Type | Description | | ---- | ---- | ----------- | -| `adminIssue` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_issue` on this resource. | -| `createDesign` | [`Boolean!`](#boolean) | Indicates the user can perform `create_design` on this resource. | -| `createNote` | [`Boolean!`](#boolean) | Indicates the user can perform `create_note` on this resource. | -| `destroyDesign` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_design` on this resource. | -| `readDesign` | [`Boolean!`](#boolean) | Indicates the user can perform `read_design` on this resource. | -| `readIssue` | [`Boolean!`](#boolean) | Indicates the user can perform `read_issue` on this resource. | -| `reopenIssue` | [`Boolean!`](#boolean) | Indicates the user can perform `reopen_issue` on this resource. | -| `updateDesign` | [`Boolean!`](#boolean) | Indicates the user can perform `update_design` on this resource. | -| `updateIssue` | [`Boolean!`](#boolean) | Indicates the user can perform `update_issue` on this resource. | +| `adminIssue` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_issue` on this resource. | +| `createDesign` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_design` on this resource. | +| `createNote` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_note` on this resource. | +| `destroyDesign` | [`Boolean!`](#boolean) | If `true`, the user can perform `destroy_design` on this resource. | +| `readDesign` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_design` on this resource. | +| `readIssue` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_issue` on this resource. | +| `reopenIssue` | [`Boolean!`](#boolean) | If `true`, the user can perform `reopen_issue` on this resource. | +| `updateDesign` | [`Boolean!`](#boolean) | If `true`, the user can perform `update_design` on this resource. | +| `updateIssue` | [`Boolean!`](#boolean) | If `true`, the user can perform `update_issue` on this resource. | ### `IssueStatusCountsType` @@ -19952,9 +19952,9 @@ Represents the Geo replication and verification state of a job_artifact. | Name | Type | Description | | ---- | ---- | ----------- | -| `readBuild` | [`Boolean!`](#boolean) | Indicates the user can perform `read_build` on this resource. | -| `readJobArtifacts` | [`Boolean!`](#boolean) | Indicates the user can perform `read_job_artifacts` on this resource. | -| `updateBuild` | [`Boolean!`](#boolean) | Indicates the user can perform `update_build` on this resource. | +| `readBuild` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_build` on this resource. | +| `readJobArtifacts` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_job_artifacts` on this resource. | +| `updateBuild` | [`Boolean!`](#boolean) | If `true`, the user can perform `update_build` on this resource. | ### `Kas` @@ -21246,16 +21246,16 @@ Check permissions for the current user on a merge request. | Name | Type | Description | | ---- | ---- | ----------- | -| `adminMergeRequest` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_merge_request` on this resource. | -| `canApprove` | [`Boolean!`](#boolean) | Indicates the user can perform `can_approve` on this resource. | -| `canMerge` | [`Boolean!`](#boolean) | Indicates the user can perform `can_merge` on this resource. | -| `cherryPickOnCurrentMergeRequest` | [`Boolean!`](#boolean) | Indicates the user can perform `cherry_pick_on_current_merge_request` on this resource. | -| `createNote` | [`Boolean!`](#boolean) | Indicates the user can perform `create_note` on this resource. | -| `pushToSourceBranch` | [`Boolean!`](#boolean) | Indicates the user can perform `push_to_source_branch` on this resource. | -| `readMergeRequest` | [`Boolean!`](#boolean) | Indicates the user can perform `read_merge_request` on this resource. | -| `removeSourceBranch` | [`Boolean!`](#boolean) | Indicates the user can perform `remove_source_branch` on this resource. | -| `revertOnCurrentMergeRequest` | [`Boolean!`](#boolean) | Indicates the user can perform `revert_on_current_merge_request` on this resource. | -| `updateMergeRequest` | [`Boolean!`](#boolean) | Indicates the user can perform `update_merge_request` on this resource. | +| `adminMergeRequest` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_merge_request` on this resource. | +| `canApprove` | [`Boolean!`](#boolean) | If `true`, the user can perform `can_approve` on this resource. | +| `canMerge` | [`Boolean!`](#boolean) | If `true`, the user can perform `can_merge` on this resource. | +| `cherryPickOnCurrentMergeRequest` | [`Boolean!`](#boolean) | If `true`, the user can perform `cherry_pick_on_current_merge_request` on this resource. | +| `createNote` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_note` on this resource. | +| `pushToSourceBranch` | [`Boolean!`](#boolean) | If `true`, the user can perform `push_to_source_branch` on this resource. | +| `readMergeRequest` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_merge_request` on this resource. | +| `removeSourceBranch` | [`Boolean!`](#boolean) | If `true`, the user can perform `remove_source_branch` on this resource. | +| `revertOnCurrentMergeRequest` | [`Boolean!`](#boolean) | If `true`, the user can perform `revert_on_current_merge_request` on this resource. | +| `updateMergeRequest` | [`Boolean!`](#boolean) | If `true`, the user can perform `update_merge_request` on this resource. | ### `MergeRequestReviewLlmSummary` @@ -21901,12 +21901,12 @@ Represents the network policy. | Name | Type | Description | | ---- | ---- | ----------- | -| `adminNote` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_note` on this resource. | -| `awardEmoji` | [`Boolean!`](#boolean) | Indicates the user can perform `award_emoji` on this resource. | -| `createNote` | [`Boolean!`](#boolean) | Indicates the user can perform `create_note` on this resource. | -| `readNote` | [`Boolean!`](#boolean) | Indicates the user can perform `read_note` on this resource. | -| `repositionNote` | [`Boolean!`](#boolean) | Indicates the user can perform `reposition_note` on this resource. | -| `resolveNote` | [`Boolean!`](#boolean) | Indicates the user can perform `resolve_note` on this resource. | +| `adminNote` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_note` on this resource. | +| `awardEmoji` | [`Boolean!`](#boolean) | If `true`, the user can perform `award_emoji` on this resource. | +| `createNote` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_note` on this resource. | +| `readNote` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_note` on this resource. | +| `repositionNote` | [`Boolean!`](#boolean) | If `true`, the user can perform `reposition_note` on this resource. | +| `resolveNote` | [`Boolean!`](#boolean) | If `true`, the user can perform `resolve_note` on this resource. | ### `NugetDependencyLinkMetadata` @@ -22579,9 +22579,9 @@ Represents pipeline counts for the project. | Name | Type | Description | | ---- | ---- | ----------- | -| `adminPipeline` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_pipeline` on this resource. | -| `destroyPipeline` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_pipeline` on this resource. | -| `updatePipeline` | [`Boolean!`](#boolean) | Indicates the user can perform `update_pipeline` on this resource. | +| `adminPipeline` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_pipeline` on this resource. | +| `destroyPipeline` | [`Boolean!`](#boolean) | If `true`, the user can perform `destroy_pipeline` on this resource. | +| `updatePipeline` | [`Boolean!`](#boolean) | If `true`, the user can perform `update_pipeline` on this resource. | ### `PipelineSchedule` @@ -22617,10 +22617,10 @@ Represents a pipeline schedule. | Name | Type | Description | | ---- | ---- | ----------- | -| `adminPipelineSchedule` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_pipeline_schedule` on this resource. | -| `playPipelineSchedule` | [`Boolean!`](#boolean) | Indicates the user can perform `play_pipeline_schedule` on this resource. | +| `adminPipelineSchedule` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_pipeline_schedule` on this resource. | +| `playPipelineSchedule` | [`Boolean!`](#boolean) | If `true`, the user can perform `play_pipeline_schedule` on this resource. | | `takeOwnershipPipelineSchedule` **{warning-solid}** | [`Boolean!`](#boolean) | **Deprecated** in 15.9. Use admin_pipeline_schedule permission to determine if the user can take ownership of a pipeline schedule. | -| `updatePipelineSchedule` | [`Boolean!`](#boolean) | Indicates the user can perform `update_pipeline_schedule` on this resource. | +| `updatePipelineSchedule` | [`Boolean!`](#boolean) | If `true`, the user can perform `update_pipeline_schedule` on this resource. | ### `PipelineScheduleVariable` @@ -24303,50 +24303,50 @@ Returns [`UserMergeRequestInteraction`](#usermergerequestinteraction). | Name | Type | Description | | ---- | ---- | ----------- | -| `adminOperations` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_operations` on this resource. | -| `adminPathLocks` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_path_locks` on this resource. | -| `adminProject` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_project` on this resource. | -| `adminRemoteMirror` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_remote_mirror` on this resource. | -| `adminWiki` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_wiki` on this resource. | -| `archiveProject` | [`Boolean!`](#boolean) | Indicates the user can perform `archive_project` on this resource. | -| `changeNamespace` | [`Boolean!`](#boolean) | Indicates the user can perform `change_namespace` on this resource. | -| `changeVisibilityLevel` | [`Boolean!`](#boolean) | Indicates the user can perform `change_visibility_level` on this resource. | -| `createDeployment` | [`Boolean!`](#boolean) | Indicates the user can perform `create_deployment` on this resource. | -| `createDesign` | [`Boolean!`](#boolean) | Indicates the user can perform `create_design` on this resource. | -| `createIssue` | [`Boolean!`](#boolean) | Indicates the user can perform `create_issue` on this resource. | -| `createLabel` | [`Boolean!`](#boolean) | Indicates the user can perform `create_label` on this resource. | -| `createMergeRequestFrom` | [`Boolean!`](#boolean) | Indicates the user can perform `create_merge_request_from` on this resource. | -| `createMergeRequestIn` | [`Boolean!`](#boolean) | Indicates the user can perform `create_merge_request_in` on this resource. | -| `createPages` | [`Boolean!`](#boolean) | Indicates the user can perform `create_pages` on this resource. | -| `createPipeline` | [`Boolean!`](#boolean) | Indicates the user can perform `create_pipeline` on this resource. | -| `createPipelineSchedule` | [`Boolean!`](#boolean) | Indicates the user can perform `create_pipeline_schedule` on this resource. | -| `createSnippet` | [`Boolean!`](#boolean) | Indicates the user can perform `create_snippet` on this resource. | -| `createWiki` | [`Boolean!`](#boolean) | Indicates the user can perform `create_wiki` on this resource. | -| `destroyDesign` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_design` on this resource. | -| `destroyPages` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_pages` on this resource. | -| `destroyWiki` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_wiki` on this resource. | -| `downloadCode` | [`Boolean!`](#boolean) | Indicates the user can perform `download_code` on this resource. | -| `downloadWikiCode` | [`Boolean!`](#boolean) | Indicates the user can perform `download_wiki_code` on this resource. | -| `forkProject` | [`Boolean!`](#boolean) | Indicates the user can perform `fork_project` on this resource. | -| `pushCode` | [`Boolean!`](#boolean) | Indicates the user can perform `push_code` on this resource. | -| `pushToDeleteProtectedBranch` | [`Boolean!`](#boolean) | Indicates the user can perform `push_to_delete_protected_branch` on this resource. | -| `readCommitStatus` | [`Boolean!`](#boolean) | Indicates the user can perform `read_commit_status` on this resource. | -| `readCycleAnalytics` | [`Boolean!`](#boolean) | Indicates the user can perform `read_cycle_analytics` on this resource. | -| `readDesign` | [`Boolean!`](#boolean) | Indicates the user can perform `read_design` on this resource. | -| `readEnvironment` | [`Boolean!`](#boolean) | Indicates the user can perform `read_environment` on this resource. | -| `readMergeRequest` | [`Boolean!`](#boolean) | Indicates the user can perform `read_merge_request` on this resource. | -| `readPagesContent` | [`Boolean!`](#boolean) | Indicates the user can perform `read_pages_content` on this resource. | -| `readProject` | [`Boolean!`](#boolean) | Indicates the user can perform `read_project` on this resource. | -| `readProjectMember` | [`Boolean!`](#boolean) | Indicates the user can perform `read_project_member` on this resource. | -| `readWiki` | [`Boolean!`](#boolean) | Indicates the user can perform `read_wiki` on this resource. | -| `removeForkProject` | [`Boolean!`](#boolean) | Indicates the user can perform `remove_fork_project` on this resource. | -| `removePages` | [`Boolean!`](#boolean) | Indicates the user can perform `remove_pages` on this resource. | -| `removeProject` | [`Boolean!`](#boolean) | Indicates the user can perform `remove_project` on this resource. | -| `renameProject` | [`Boolean!`](#boolean) | Indicates the user can perform `rename_project` on this resource. | -| `requestAccess` | [`Boolean!`](#boolean) | Indicates the user can perform `request_access` on this resource. | -| `updatePages` | [`Boolean!`](#boolean) | Indicates the user can perform `update_pages` on this resource. | -| `updateWiki` | [`Boolean!`](#boolean) | Indicates the user can perform `update_wiki` on this resource. | -| `uploadFile` | [`Boolean!`](#boolean) | Indicates the user can perform `upload_file` on this resource. | +| `adminOperations` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_operations` on this resource. | +| `adminPathLocks` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_path_locks` on this resource. | +| `adminProject` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_project` on this resource. | +| `adminRemoteMirror` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_remote_mirror` on this resource. | +| `adminWiki` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_wiki` on this resource. | +| `archiveProject` | [`Boolean!`](#boolean) | If `true`, the user can perform `archive_project` on this resource. | +| `changeNamespace` | [`Boolean!`](#boolean) | If `true`, the user can perform `change_namespace` on this resource. | +| `changeVisibilityLevel` | [`Boolean!`](#boolean) | If `true`, the user can perform `change_visibility_level` on this resource. | +| `createDeployment` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_deployment` on this resource. | +| `createDesign` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_design` on this resource. | +| `createIssue` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_issue` on this resource. | +| `createLabel` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_label` on this resource. | +| `createMergeRequestFrom` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_merge_request_from` on this resource. | +| `createMergeRequestIn` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_merge_request_in` on this resource. | +| `createPages` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_pages` on this resource. | +| `createPipeline` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_pipeline` on this resource. | +| `createPipelineSchedule` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_pipeline_schedule` on this resource. | +| `createSnippet` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_snippet` on this resource. | +| `createWiki` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_wiki` on this resource. | +| `destroyDesign` | [`Boolean!`](#boolean) | If `true`, the user can perform `destroy_design` on this resource. | +| `destroyPages` | [`Boolean!`](#boolean) | If `true`, the user can perform `destroy_pages` on this resource. | +| `destroyWiki` | [`Boolean!`](#boolean) | If `true`, the user can perform `destroy_wiki` on this resource. | +| `downloadCode` | [`Boolean!`](#boolean) | If `true`, the user can perform `download_code` on this resource. | +| `downloadWikiCode` | [`Boolean!`](#boolean) | If `true`, the user can perform `download_wiki_code` on this resource. | +| `forkProject` | [`Boolean!`](#boolean) | If `true`, the user can perform `fork_project` on this resource. | +| `pushCode` | [`Boolean!`](#boolean) | If `true`, the user can perform `push_code` on this resource. | +| `pushToDeleteProtectedBranch` | [`Boolean!`](#boolean) | If `true`, the user can perform `push_to_delete_protected_branch` on this resource. | +| `readCommitStatus` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_commit_status` on this resource. | +| `readCycleAnalytics` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_cycle_analytics` on this resource. | +| `readDesign` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_design` on this resource. | +| `readEnvironment` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_environment` on this resource. | +| `readMergeRequest` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_merge_request` on this resource. | +| `readPagesContent` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_pages_content` on this resource. | +| `readProject` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_project` on this resource. | +| `readProjectMember` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_project_member` on this resource. | +| `readWiki` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_wiki` on this resource. | +| `removeForkProject` | [`Boolean!`](#boolean) | If `true`, the user can perform `remove_fork_project` on this resource. | +| `removePages` | [`Boolean!`](#boolean) | If `true`, the user can perform `remove_pages` on this resource. | +| `removeProject` | [`Boolean!`](#boolean) | If `true`, the user can perform `remove_project` on this resource. | +| `renameProject` | [`Boolean!`](#boolean) | If `true`, the user can perform `rename_project` on this resource. | +| `requestAccess` | [`Boolean!`](#boolean) | If `true`, the user can perform `request_access` on this resource. | +| `updatePages` | [`Boolean!`](#boolean) | If `true`, the user can perform `update_pages` on this resource. | +| `updateWiki` | [`Boolean!`](#boolean) | If `true`, the user can perform `update_wiki` on this resource. | +| `uploadFile` | [`Boolean!`](#boolean) | If `true`, the user can perform `upload_file` on this resource. | ### `ProjectRepositoryRegistry` @@ -25045,11 +25045,11 @@ Check permissions for the current user on a requirement. | Name | Type | Description | | ---- | ---- | ----------- | -| `adminRequirement` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_requirement` on this resource. | -| `createRequirement` | [`Boolean!`](#boolean) | Indicates the user can perform `create_requirement` on this resource. | -| `destroyRequirement` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_requirement` on this resource. | -| `readRequirement` | [`Boolean!`](#boolean) | Indicates the user can perform `read_requirement` on this resource. | -| `updateRequirement` | [`Boolean!`](#boolean) | Indicates the user can perform `update_requirement` on this resource. | +| `adminRequirement` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_requirement` on this resource. | +| `createRequirement` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_requirement` on this resource. | +| `destroyRequirement` | [`Boolean!`](#boolean) | If `true`, the user can perform `destroy_requirement` on this resource. | +| `readRequirement` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_requirement` on this resource. | +| `updateRequirement` | [`Boolean!`](#boolean) | If `true`, the user can perform `update_requirement` on this resource. | ### `RequirementStatesCount` @@ -25098,10 +25098,10 @@ Counts of requirements by their state. | Name | Type | Description | | ---- | ---- | ----------- | -| `assignRunner` | [`Boolean!`](#boolean) | Indicates the user can perform `assign_runner` on this resource. | -| `deleteRunner` | [`Boolean!`](#boolean) | Indicates the user can perform `delete_runner` on this resource. | -| `readRunner` | [`Boolean!`](#boolean) | Indicates the user can perform `read_runner` on this resource. | -| `updateRunner` | [`Boolean!`](#boolean) | Indicates the user can perform `update_runner` on this resource. | +| `assignRunner` | [`Boolean!`](#boolean) | If `true`, the user can perform `assign_runner` on this resource. | +| `deleteRunner` | [`Boolean!`](#boolean) | If `true`, the user can perform `delete_runner` on this resource. | +| `readRunner` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_runner` on this resource. | +| `updateRunner` | [`Boolean!`](#boolean) | If `true`, the user can perform `update_runner` on this resource. | ### `RunnerPlatform` @@ -25595,12 +25595,12 @@ Represents how the blob content should be displayed. | Name | Type | Description | | ---- | ---- | ----------- | -| `adminSnippet` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_snippet` on this resource. | -| `awardEmoji` | [`Boolean!`](#boolean) | Indicates the user can perform `award_emoji` on this resource. | -| `createNote` | [`Boolean!`](#boolean) | Indicates the user can perform `create_note` on this resource. | -| `readSnippet` | [`Boolean!`](#boolean) | Indicates the user can perform `read_snippet` on this resource. | -| `reportSnippet` | [`Boolean!`](#boolean) | Indicates the user can perform `report_snippet` on this resource. | -| `updateSnippet` | [`Boolean!`](#boolean) | Indicates the user can perform `update_snippet` on this resource. | +| `adminSnippet` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_snippet` on this resource. | +| `awardEmoji` | [`Boolean!`](#boolean) | If `true`, the user can perform `award_emoji` on this resource. | +| `createNote` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_note` on this resource. | +| `readSnippet` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_snippet` on this resource. | +| `reportSnippet` | [`Boolean!`](#boolean) | If `true`, the user can perform `report_snippet` on this resource. | +| `updateSnippet` | [`Boolean!`](#boolean) | If `true`, the user can perform `update_snippet` on this resource. | ### `SnippetRepositoryRegistry` @@ -25985,7 +25985,7 @@ Describes an incident management timeline event. | Name | Type | Description | | ---- | ---- | ----------- | -| `adminTimelog` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_timelog` on this resource. | +| `adminTimelog` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_timelog` on this resource. | ### `Todo` @@ -26435,7 +26435,7 @@ fields relate to interactions between the two entities. | Name | Type | Description | | ---- | ---- | ----------- | -| `createSnippet` | [`Boolean!`](#boolean) | Indicates the user can perform `create_snippet` on this resource. | +| `createSnippet` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_snippet` on this resource. | ### `UserPreferences` @@ -27029,15 +27029,15 @@ Check permissions for the current user on a vulnerability. | Name | Type | Description | | ---- | ---- | ----------- | -| `adminVulnerability` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_vulnerability` on this resource. | -| `adminVulnerabilityExternalIssueLink` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_vulnerability_external_issue_link` on this resource. | -| `adminVulnerabilityIssueLink` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_vulnerability_issue_link` on this resource. | -| `createVulnerabilityExport` | [`Boolean!`](#boolean) | Indicates the user can perform `create_vulnerability_export` on this resource. | -| `createVulnerabilityFeedback` | [`Boolean!`](#boolean) | Indicates the user can perform `create_vulnerability_feedback` on this resource. | -| `destroyVulnerabilityFeedback` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_vulnerability_feedback` on this resource. | -| `readVulnerability` | [`Boolean!`](#boolean) | Indicates the user can perform `read_vulnerability` on this resource. | -| `readVulnerabilityFeedback` | [`Boolean!`](#boolean) | Indicates the user can perform `read_vulnerability_feedback` on this resource. | -| `updateVulnerabilityFeedback` | [`Boolean!`](#boolean) | Indicates the user can perform `update_vulnerability_feedback` on this resource. | +| `adminVulnerability` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_vulnerability` on this resource. | +| `adminVulnerabilityExternalIssueLink` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_vulnerability_external_issue_link` on this resource. | +| `adminVulnerabilityIssueLink` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_vulnerability_issue_link` on this resource. | +| `createVulnerabilityExport` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_vulnerability_export` on this resource. | +| `createVulnerabilityFeedback` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_vulnerability_feedback` on this resource. | +| `destroyVulnerabilityFeedback` | [`Boolean!`](#boolean) | If `true`, the user can perform `destroy_vulnerability_feedback` on this resource. | +| `readVulnerability` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_vulnerability` on this resource. | +| `readVulnerabilityFeedback` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_vulnerability_feedback` on this resource. | +| `updateVulnerabilityFeedback` | [`Boolean!`](#boolean) | If `true`, the user can perform `update_vulnerability_feedback` on this resource. | ### `VulnerabilityRemediationType` @@ -27230,14 +27230,14 @@ Check permissions for the current user on a work item. | Name | Type | Description | | ---- | ---- | ----------- | -| `adminParentLink` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_parent_link` on this resource. | -| `adminWorkItem` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_work_item` on this resource. | -| `adminWorkItemLink` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_work_item_link` on this resource. | -| `createNote` | [`Boolean!`](#boolean) | Indicates the user can perform `create_note` on this resource. | -| `deleteWorkItem` | [`Boolean!`](#boolean) | Indicates the user can perform `delete_work_item` on this resource. | -| `readWorkItem` | [`Boolean!`](#boolean) | Indicates the user can perform `read_work_item` on this resource. | -| `setWorkItemMetadata` | [`Boolean!`](#boolean) | Indicates the user can perform `set_work_item_metadata` on this resource. | -| `updateWorkItem` | [`Boolean!`](#boolean) | Indicates the user can perform `update_work_item` on this resource. | +| `adminParentLink` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_parent_link` on this resource. | +| `adminWorkItem` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_work_item` on this resource. | +| `adminWorkItemLink` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_work_item_link` on this resource. | +| `createNote` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_note` on this resource. | +| `deleteWorkItem` | [`Boolean!`](#boolean) | If `true`, the user can perform `delete_work_item` on this resource. | +| `readWorkItem` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_work_item` on this resource. | +| `setWorkItemMetadata` | [`Boolean!`](#boolean) | If `true`, the user can perform `set_work_item_metadata` on this resource. | +| `updateWorkItem` | [`Boolean!`](#boolean) | If `true`, the user can perform `update_work_item` on this resource. | ### `WorkItemType` diff --git a/doc/api/scim.md b/doc/api/scim.md index 8840935e646..86a5729735e 100644 --- a/doc/api/scim.md +++ b/doc/api/scim.md @@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98354) in GitLab 15.5. -The GitLab SCIM API manages SCIM identities within groups and provides the `/Users` endpoint. The base URL is `/api/scim/v2/groups/:group_path/Users/`. +The GitLab SCIM API manages SCIM identities within groups and provides the `/groups/:groups_id/scim/identities` and `/groups/:groups_id/scim/:uid` endpoints. The base URL is `:///api/v4`. To use this API, [Group SSO](../user/group/saml_sso/index.md) must be enabled for the group. This API is only in use where [SCIM for Group SSO](../user/group/saml_sso/scim_setup.md) is enabled. It's a prerequisite to the creation of SCIM identities. diff --git a/doc/development/internal_api/index.md b/doc/development/internal_api/index.md index f9b494b80c2..9b5bafaad8f 100644 --- a/doc/development/internal_api/index.md +++ b/doc/development/internal_api/index.md @@ -1215,7 +1215,7 @@ Example response: > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9388) in GitLab 11.10. -The group SCIM API implements the [RFC7644 protocol](https://www.rfc-editor.org/rfc/rfc7644). As this API is for +The group SCIM API partially implements the [RFC7644 protocol](https://www.rfc-editor.org/rfc/rfc7644). This API provides the `/groups/:group_path/Users` and `/groups/:group_path/Users/:id` endpoints. The base URL is `:///api/scim/v2`. Because this API is for **system** use for SCIM provider integration, it is subject to change without notice. To use this API, enable [Group SSO](../../user/group/saml_sso/index.md) for the group. @@ -1452,7 +1452,7 @@ Returns an empty response with a `204` status code if successful. > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/378599) in GitLab 15.8. -The Instance SCIM API implements the [RFC7644 protocol](https://www.rfc-editor.org/rfc/rfc7644). As this API is for +The instance SCIM API partially implements the [RFC7644 protocol](https://www.rfc-editor.org/rfc/rfc7644). This API provides the `/application/Users` and `/application/Users/:id` endpoints. The base URL is `:///api/scim/v2`. Because this API is for **system** use for SCIM provider integration, it is subject to change without notice. To use this API, enable [SAML SSO](../../integration/saml.md) for the instance. diff --git a/lib/api/helm_packages.rb b/lib/api/helm_packages.rb index 8260d8a88f8..c811f47cb5b 100644 --- a/lib/api/helm_packages.rb +++ b/lib/api/helm_packages.rb @@ -75,6 +75,8 @@ module API requires :file_name, type: String, desc: 'Helm package file name', documentation: { example: 'mychart' } end get ":channel/charts/:file_name.tgz" do + not_found!("Format #{params[:format]}") unless params[:format].nil? + project = authorized_user_project(action: :read_package) authorize_read_package!(project) diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index dbeacda01ea..a7e0a551283 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -897,7 +897,7 @@ module API def project_moved?(id, project) return false unless Feature.enabled?(:api_redirect_moved_projects) return false unless id.is_a?(String) && id.include?('/') - return false if project.blank? || id == project.full_path + return false if project.blank? || project.full_path.casecmp?(id) return false unless params[:id] == id true diff --git a/lib/gitlab/ci/yaml_processor/dag.rb b/lib/gitlab/ci/yaml_processor/dag.rb index 4a122c73e80..ad78277080b 100644 --- a/lib/gitlab/ci/yaml_processor/dag.rb +++ b/lib/gitlab/ci/yaml_processor/dag.rb @@ -24,6 +24,8 @@ module Gitlab def tsort_each_child(node, &block) return unless @nodes[node] + raise TSort::Cyclic, /topological sort failed/ if @nodes[node].include?(node) + @nodes[node].each(&block) end diff --git a/lib/gitlab/internal_events.rb b/lib/gitlab/internal_events.rb index 2790bc8ee24..e2e4ea75dbf 100644 --- a/lib/gitlab/internal_events.rb +++ b/lib/gitlab/internal_events.rb @@ -23,8 +23,6 @@ module Gitlab private def increase_total_counter(event_name) - return unless ::ServicePing::ServicePingSettings.enabled? - redis_counter_key = Gitlab::Usage::Metrics::Instrumentations::TotalCountMetric.redis_key(event_name) Gitlab::Redis::SharedState.with { |redis| redis.incr(redis_counter_key) } diff --git a/lib/gitlab/usage_data_counters/hll_redis_counter.rb b/lib/gitlab/usage_data_counters/hll_redis_counter.rb index 5c27bfe297f..185b49d4a68 100644 --- a/lib/gitlab/usage_data_counters/hll_redis_counter.rb +++ b/lib/gitlab/usage_data_counters/hll_redis_counter.rb @@ -56,8 +56,6 @@ module Gitlab private def track(values, event_name, time: Time.zone.now) - return unless ::ServicePing::ServicePingSettings.enabled? - event = event_for(event_name) Gitlab::ErrorTracking.track_and_raise_for_dev_exception(UnknownEvent.new("Unknown event #{event_name}")) unless event.present? diff --git a/lib/gitlab/usage_data_counters/redis_counter.rb b/lib/gitlab/usage_data_counters/redis_counter.rb index 6f887fe6106..3f16681b642 100644 --- a/lib/gitlab/usage_data_counters/redis_counter.rb +++ b/lib/gitlab/usage_data_counters/redis_counter.rb @@ -7,14 +7,10 @@ module Gitlab module UsageDataCounters module RedisCounter def increment(redis_counter_key) - return unless ::ServicePing::ServicePingSettings.enabled? - Gitlab::Redis::SharedState.with { |redis| redis.incr(redis_counter_key) } end def increment_by(redis_counter_key, incr) - return unless ::ServicePing::ServicePingSettings.enabled? - Gitlab::Redis::SharedState.with { |redis| redis.incrby(redis_counter_key, incr) } end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index c98b7517327..c658795361c 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -12322,6 +12322,15 @@ msgstr "" msgid "Compliance framework" msgstr "" +msgid "ComplianceFrameworksReport|Associated Projects" +msgstr "" + +msgid "ComplianceFrameworksReport|Default" +msgstr "" + +msgid "ComplianceFrameworksReport|Edit framework" +msgstr "" + msgid "ComplianceFrameworks|Active compliance frameworks" msgstr "" @@ -55804,6 +55813,9 @@ msgstr "" msgid "and" msgstr "" +msgid "any-approver for the group already exists" +msgstr "" + msgid "any-approver for the merge request already exists" msgstr "" diff --git a/qa/Gemfile b/qa/Gemfile index a52385d314b..06de6004742 100644 --- a/qa/Gemfile +++ b/qa/Gemfile @@ -9,7 +9,7 @@ gem 'activesupport', '~> 7.0.8' # This should stay in sync with the root's Gemfi gem 'allure-rspec', '~> 2.20.0' gem 'capybara', '~> 3.39.2' gem 'capybara-screenshot', '~> 1.0.26' -gem 'rake', '~> 13', '>= 13.0.6' +gem 'rake', '~> 13', '>= 13.1.0' gem 'rspec', '~> 3.12' gem 'selenium-webdriver', '= 4.14.0' gem 'airborne', '~> 0.3.7', require: false # airborne is messing with rspec sandboxed mode so not requiring by default diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock index 30fd3691521..81602f9ecce 100644 --- a/qa/Gemfile.lock +++ b/qa/Gemfile.lock @@ -246,7 +246,7 @@ GEM rails-html-sanitizer (1.5.0) loofah (~> 2.19, >= 2.19.1) rainbow (3.1.1) - rake (13.0.6) + rake (13.1.0) regexp_parser (2.1.1) representable (3.2.0) declarative (< 0.1.0) @@ -362,7 +362,7 @@ DEPENDENCIES parallel_tests (~> 4.2, >= 4.2.1) pry-byebug (~> 3.10.1) rainbow (~> 3.1.1) - rake (~> 13, >= 13.0.6) + rake (~> 13, >= 13.1.0) rest-client (~> 2.1.0) rotp (~> 6.3.0) rspec (~> 3.12) @@ -377,4 +377,4 @@ DEPENDENCIES zeitwerk (~> 2.6, >= 2.6.8) BUNDLED WITH - 2.4.20 + 2.4.21 diff --git a/spec/frontend/fixtures/issues.rb b/spec/frontend/fixtures/issues.rb index 90aa0544526..6d81d9ca1d2 100644 --- a/spec/frontend/fixtures/issues.rb +++ b/spec/frontend/fixtures/issues.rb @@ -5,7 +5,7 @@ require 'spec_helper' RSpec.describe Projects::IssuesController, '(JavaScript fixtures)', :with_license, type: :controller do include JavaScriptFixturesHelpers - let(:user) { create(:user, :no_super_sidebar, feed_token: 'feedtoken:coldfeed') } + let(:user) { create(:user, feed_token: 'feedtoken:coldfeed') } let(:namespace) { create(:namespace, name: 'frontend-fixtures') } let(:project) { create(:project_empty_repo, namespace: namespace, path: 'issues-project') } diff --git a/spec/frontend/fixtures/snippet.rb b/spec/frontend/fixtures/snippet.rb index 23df89a244c..a96b7a57106 100644 --- a/spec/frontend/fixtures/snippet.rb +++ b/spec/frontend/fixtures/snippet.rb @@ -5,7 +5,7 @@ require 'spec_helper' RSpec.describe SnippetsController, '(JavaScript fixtures)', type: :controller do include JavaScriptFixturesHelpers - let(:user) { create(:user, :no_super_sidebar) } + let(:user) { create(:user) } let(:namespace) { create(:namespace, name: 'frontend-fixtures', owner: user) } let(:project) { create(:project, :repository, namespace: namespace, path: 'branches-project') } let(:snippet) { create(:personal_snippet, :public, title: 'snippet.md', content: '# snippet', file_name: 'snippet.md', author: user) } diff --git a/spec/frontend/header_spec.js b/spec/frontend/header_spec.js index 4907dc09a3c..13c11863443 100644 --- a/spec/frontend/header_spec.js +++ b/spec/frontend/header_spec.js @@ -3,7 +3,14 @@ import { mockTracking, unmockTracking } from 'helpers/tracking_helper'; import initTodoToggle, { initNavUserDropdownTracking } from '~/header'; import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures'; -describe('Header', () => { +// TODO: Remove this with the removal of the old navigation. +// See https://gitlab.com/groups/gitlab-org/-/epics/11875. +// +// This and ~/header will be removed. These tests no longer work due to the +// corresponding fixtures changing for +// https://gitlab.com/gitlab-org/gitlab/-/issues/420121. +// eslint-disable-next-line jest/no-disabled-tests +describe.skip('Header', () => { describe('Todos notification', () => { const todosPendingCount = '.js-todos-count'; diff --git a/spec/frontend/ide/components/repo_editor_spec.js b/spec/frontend/ide/components/repo_editor_spec.js index 33fa5bc799f..6f53aaed655 100644 --- a/spec/frontend/ide/components/repo_editor_spec.js +++ b/spec/frontend/ide/components/repo_editor_spec.js @@ -8,17 +8,14 @@ import { shallowMount } from '@vue/test-utils'; import waitForPromises from 'helpers/wait_for_promises'; import { stubPerformanceWebAPI } from 'helpers/performance'; import { exampleConfigs, exampleFiles } from 'jest/ide/lib/editorconfig/mock_data'; -import { - EDITOR_CODE_INSTANCE_FN, - EDITOR_DIFF_INSTANCE_FN, - EXTENSION_CI_SCHEMA_FILE_NAME_MATCH, -} from '~/editor/constants'; +import { EDITOR_CODE_INSTANCE_FN, EDITOR_DIFF_INSTANCE_FN } from '~/editor/constants'; import { EditorMarkdownExtension } from '~/editor/extensions/source_editor_markdown_ext'; import { EditorMarkdownPreviewExtension } from '~/editor/extensions/source_editor_markdown_livepreview_ext'; import { CiSchemaExtension } from '~/editor/extensions/source_editor_ci_schema_ext'; import SourceEditor from '~/editor/source_editor'; import RepoEditor from '~/ide/components/repo_editor.vue'; import { leftSidebarViews, FILE_VIEW_MODE_PREVIEW, viewerTypes } from '~/ide/constants'; +import { DEFAULT_CI_CONFIG_PATH } from '~/lib/utils/constants'; import ModelManager from '~/ide/lib/common/model_manager'; import service from '~/ide/services'; import { createStoreOptions } from '~/ide/stores'; @@ -56,7 +53,7 @@ const dummyFile = { active: true, }, ciConfig: { - ...file(EXTENSION_CI_SCHEMA_FILE_NAME_MATCH), + ...file(DEFAULT_CI_CONFIG_PATH), content: '', tempFile: true, active: true, diff --git a/spec/frontend/issues/issue_spec.js b/spec/frontend/issues/issue_spec.js index bf2ca42f71f..b976a051f7a 100644 --- a/spec/frontend/issues/issue_spec.js +++ b/spec/frontend/issues/issue_spec.js @@ -58,7 +58,17 @@ describe('Issue', () => { ); }); - it('updates issueCounter text', () => { + // TODO: Remove this with the removal of the old navigation. + // See https://gitlab.com/groups/gitlab-org/-/epics/11875. + // See also https://gitlab.com/gitlab-org/gitlab/-/issues/429678 about + // reimplementing this in the new navigation. + // + // Since this entire suite only tests the issue count updating, removing + // this test would mean removing the entire suite. But, ~/issues/issue.js + // does more than just that. Tests should be written to cover those other + // features. So we're just skipping this for now. + // eslint-disable-next-line jest/no-disabled-tests + it.skip('updates issueCounter text', () => { expect(testContext.issueCounter).toBeVisible(); expect(testContext.issueCounter).toHaveText(expectedCounterText); }); diff --git a/spec/frontend/lib/utils/common_utils_spec.js b/spec/frontend/lib/utils/common_utils_spec.js index 8697249ebf5..6295914b127 100644 --- a/spec/frontend/lib/utils/common_utils_spec.js +++ b/spec/frontend/lib/utils/common_utils_spec.js @@ -1213,4 +1213,28 @@ describe('common_utils', () => { expect(cloned.ref === ref).toBe(false); }); }); + + describe('isDefaultCiConfig', () => { + it('returns true when the path is the default CI config path', () => { + expect(commonUtils.isDefaultCiConfig('.gitlab-ci.yml')).toBe(true); + }); + + it('returns false when the path is not the default CI config path', () => { + expect(commonUtils.isDefaultCiConfig('some/other/path.yml')).toBe(false); + }); + }); + + describe('hasCiConfigExtension', () => { + it('returns true when the path is the default CI config path', () => { + expect(commonUtils.hasCiConfigExtension('.gitlab-ci.yml')).toBe(true); + }); + + it('returns true when the path has a CI config extension', () => { + expect(commonUtils.hasCiConfigExtension('some/path.gitlab-ci.yml')).toBe(true); + }); + + it('returns false when the path does not have a CI config extension', () => { + expect(commonUtils.hasCiConfigExtension('some/other/path.yml')).toBe(false); + }); + }); }); diff --git a/spec/frontend/shortcuts_spec.js b/spec/frontend/shortcuts_spec.js index 88ad9204d08..ca72426cb44 100644 --- a/spec/frontend/shortcuts_spec.js +++ b/spec/frontend/shortcuts_spec.js @@ -7,23 +7,26 @@ import Shortcuts, { LOCAL_MOUSETRAP_DATA_KEY } from '~/behaviors/shortcuts/short import MarkdownPreview from '~/behaviors/preview_markdown'; describe('Shortcuts', () => { - const createEvent = (type, target) => - $.Event(type, { - target, - }); let shortcuts; beforeAll(() => { shortcuts = new Shortcuts(); }); + const mockSuperSidebarSearchButton = () => { + const button = document.createElement('button'); + button.id = 'super-sidebar-search'; + return button; + }; + beforeEach(() => { setHTMLFixture(htmlSnippetsShow); + document.body.appendChild(mockSuperSidebarSearchButton()); new Shortcuts(); // eslint-disable-line no-new new MarkdownPreview(); // eslint-disable-line no-new - jest.spyOn(document.querySelector('#search'), 'focus'); + jest.spyOn(HTMLElement.prototype, 'click'); jest.spyOn(Mousetrap.prototype, 'stopCallback'); jest.spyOn(Mousetrap.prototype, 'bind').mockImplementation(); @@ -100,21 +103,22 @@ describe('Shortcuts', () => { }); describe('focusSearch', () => { - describe('when super sidebar is NOT enabled', () => { - let originalGon; - beforeEach(() => { - originalGon = window.gon; - window.gon = { use_new_navigation: false }; - }); + let event; - afterEach(() => { - window.gon = originalGon; - }); + beforeEach(() => { + window.gon.use_new_navigation = true; + event = new KeyboardEvent('keydown', { cancelable: true }); + Shortcuts.focusSearch(event); + }); - it('focuses the search bar', () => { - Shortcuts.focusSearch(createEvent('KeyboardEvent')); - expect(document.querySelector('#search').focus).toHaveBeenCalled(); - }); + it('clicks the super sidebar search button', () => { + expect(HTMLElement.prototype.click).toHaveBeenCalled(); + const thisArg = HTMLElement.prototype.click.mock.contexts[0]; + expect(thisArg.id).toBe('super-sidebar-search'); + }); + + it('cancels the default behaviour of the event', () => { + expect(event.defaultPrevented).toBe(true); }); }); diff --git a/spec/frontend/vue_shared/components/list_selector/index_spec.js b/spec/frontend/vue_shared/components/list_selector/index_spec.js new file mode 100644 index 00000000000..96074519857 --- /dev/null +++ b/spec/frontend/vue_shared/components/list_selector/index_spec.js @@ -0,0 +1,134 @@ +import Vue from 'vue'; +import VueApollo from 'vue-apollo'; +import { GlCard, GlIcon, GlCollapsibleListbox, GlSearchBoxByType } from '@gitlab/ui'; +import { mountExtended } from 'helpers/vue_test_utils_helper'; +import ListSelector from '~/vue_shared/components/list_selector/index.vue'; +import User from '~/vue_shared/components/list_selector/user.vue'; +import usersAutocompleteQuery from '~/graphql_shared/queries/users_autocomplete.query.graphql'; +import createMockApollo from 'helpers/mock_apollo_helper'; +import waitForPromises from 'helpers/wait_for_promises'; +import { USERS_RESPONSE_MOCK } from './mock_data'; + +Vue.use(VueApollo); + +describe('List Selector spec', () => { + let wrapper; + let fakeApollo; + + const MOCK_PROPS = { + title: 'Users', + projectPath: 'some/project/path', + type: 'users', + }; + + const usersAutocompleteQuerySuccess = jest.fn().mockResolvedValue(USERS_RESPONSE_MOCK); + + const createComponent = async (props) => { + fakeApollo = createMockApollo([[usersAutocompleteQuery, usersAutocompleteQuerySuccess]]); + + wrapper = mountExtended(ListSelector, { + apolloProvider: fakeApollo, + propsData: { + ...MOCK_PROPS, + ...props, + }, + }); + + await waitForPromises(); + }; + + const findCard = () => wrapper.findComponent(GlCard); + const findTitle = () => wrapper.findByText(MOCK_PROPS.title); + const findIcon = () => wrapper.findComponent(GlIcon); + const findListBox = () => wrapper.findComponent(GlCollapsibleListbox); + const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType); + const findAllUserComponents = () => wrapper.findAllComponents(User); + + describe('Users type', () => { + beforeEach(() => createComponent({ type: 'users' })); + + it('renders a Card component', () => { + expect(findCard().exists()).toBe(true); + }); + + it('renders a title', () => { + expect(findTitle().exists()).toBe(true); + }); + + it('renders the correct icon', () => { + expect(findIcon().props('name')).toBe('user'); + }); + + it('renders a Search box component', () => { + expect(findSearchBox().exists()).toBe(true); + }); + + it('does not call query when search box has not received an input', () => { + expect(usersAutocompleteQuerySuccess).not.toHaveBeenCalled(); + expect(findAllUserComponents().length).toBe(0); + }); + + describe('searching', () => { + const searchResponse = USERS_RESPONSE_MOCK.data.project.autocompleteUsers; + const search = 'foo'; + + const emitSearchInput = async () => { + findSearchBox().vm.$emit('input', search); + await waitForPromises(); + }; + + beforeEach(() => emitSearchInput()); + + it('calls query with correct variables when Search box receives an input', () => { + expect(usersAutocompleteQuerySuccess).toHaveBeenCalledWith({ + fullPath: MOCK_PROPS.projectPath, + isProject: true, + search, + }); + }); + + it('renders a List box component with the correct props', () => { + expect(findListBox().props()).toMatchObject({ multiple: true, items: searchResponse }); + }); + + it('renders a user component for each search result', () => { + expect(findAllUserComponents().length).toBe(searchResponse.length); + }); + + it('emits an event when a search result is selected', () => { + const firstSearchResult = searchResponse[0]; + findAllUserComponents().at(0).vm.$emit('select', firstSearchResult.username); + + expect(wrapper.emitted('select')).toEqual([ + [{ ...firstSearchResult, text: 'Administrator', value: 'root' }], + ]); + }); + }); + + describe('selected items', () => { + const selectedUser = { username: 'root' }; + const selectedItems = [selectedUser]; + beforeEach(() => createComponent({ selectedItems })); + + it('renders a heading with the total selected items', () => { + expect(findCard().text()).toContain('Users'); + expect(findCard().text()).toContain('1'); + }); + + it('renders a user component for each selected item', () => { + expect(findAllUserComponents().length).toBe(selectedItems.length); + expect(findAllUserComponents().at(0).props()).toMatchObject({ + data: selectedUser, + canDelete: true, + }); + }); + + it('emits a delete event when a delete event is emitted from the user component', () => { + const username = 'root'; + findAllUserComponents().at(0).vm.$emit('delete', username); + + expect(wrapper.emitted('delete')).toEqual([[username]]); + }); + }); + }); +}); diff --git a/spec/frontend/vue_shared/components/list_selector/mock_data.js b/spec/frontend/vue_shared/components/list_selector/mock_data.js new file mode 100644 index 00000000000..ce5d209a938 --- /dev/null +++ b/spec/frontend/vue_shared/components/list_selector/mock_data.js @@ -0,0 +1,25 @@ +export const USERS_RESPONSE_MOCK = { + data: { + project: { + id: 'gid://gitlab/Project/20', + autocompleteUsers: [ + { + id: 'gid://gitlab/User/1', + avatarUrl: '/uploads/-/system/user/avatar/1/avatar.png', + name: 'Administrator', + username: 'root', + __typename: 'AutocompletedUser', + }, + { + id: 'gid://gitlab/User/15', + avatarUrl: + 'https://www.gravatar.com/avatar/c4ab964b90c3049c47882b319d3c5cc0?s=80\u0026d=identicon', + name: 'Corrine Rath', + username: 'laronda.graham', + __typename: 'AutocompletedUser', + }, + ], + __typename: 'Project', + }, + }, +}; diff --git a/spec/frontend/vue_shared/components/list_selector/user_spec.js b/spec/frontend/vue_shared/components/list_selector/user_spec.js new file mode 100644 index 00000000000..5ce21f6672b --- /dev/null +++ b/spec/frontend/vue_shared/components/list_selector/user_spec.js @@ -0,0 +1,55 @@ +import { GlAvatar } from '@gitlab/ui'; +import { mountExtended } from 'helpers/vue_test_utils_helper'; +import User from '~/vue_shared/components/list_selector/user.vue'; + +describe('User spec', () => { + let wrapper; + + const MOCK_USER = { name: 'Admin', username: 'root', avatarUrl: 'some/avatar.jpg' }; + + const createComponent = (props) => { + wrapper = mountExtended(User, { + propsData: { + data: MOCK_USER, + ...props, + }, + }); + }; + + const findAvatar = () => wrapper.findComponent(GlAvatar); + const findDeleteButton = () => wrapper.findByRole('button', { name: 'Delete Admin' }); + + beforeEach(() => createComponent()); + + it('renders an Avatar component', () => { + expect(findAvatar().props('size')).toBe(32); + expect(findAvatar().attributes()).toMatchObject({ + src: MOCK_USER.avatarUrl, + alt: MOCK_USER.name, + }); + }); + + it('renders a name and username', () => { + expect(wrapper.text()).toContain('Admin'); + expect(wrapper.text()).toContain('@root'); + }); + + it('does not render a delete button by default', () => { + expect(findDeleteButton().exists()).toBe(false); + }); + + describe('Delete button', () => { + beforeEach(() => createComponent({ canDelete: true })); + + it('renders a delete button', () => { + expect(findDeleteButton().exists()).toBe(true); + expect(findDeleteButton().props('icon')).toBe('remove'); + }); + + it('emits a delete event if the delete button is clicked', () => { + findDeleteButton().trigger('click'); + + expect(wrapper.emitted('delete')).toEqual([[MOCK_USER.username]]); + }); + }); +}); diff --git a/spec/graphql/mutations/base_mutation_spec.rb b/spec/graphql/mutations/base_mutation_spec.rb deleted file mode 100644 index a73d914f48f..00000000000 --- a/spec/graphql/mutations/base_mutation_spec.rb +++ /dev/null @@ -1,58 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe ::Mutations::BaseMutation, feature_category: :api do - include GraphqlHelpers - - describe 'argument nullability' do - let_it_be(:user) { create(:user) } - let_it_be(:context) { { current_user: user } } - - subject(:mutation) { mutation_class.new(object: nil, context: context, field: nil) } - - describe 'when using a mutation with correct argument declarations' do - context 'when argument is nullable and required' do - let(:mutation_class) do - Class.new(described_class) do - graphql_name 'BaseMutation' - argument :foo, GraphQL::Types::String, required: :nullable - end - end - - specify do - expect { subject.ready? }.to raise_error(ArgumentError, /must be provided: foo/) - end - - specify do - expect { subject.ready?(foo: nil) }.not_to raise_error - end - - specify do - expect { subject.ready?(foo: "bar") }.not_to raise_error - end - end - - context 'when argument is required and NOT nullable' do - let(:mutation_class) do - Class.new(described_class) do - graphql_name 'BaseMutation' - argument :foo, GraphQL::Types::String, required: true - end - end - - specify do - expect { subject.ready? }.to raise_error(ArgumentError, /must be provided/) - end - - specify do - expect { subject.ready?(foo: nil) }.to raise_error(ArgumentError, /must be provided/) - end - - specify do - expect { subject.ready?(foo: "bar") }.not_to raise_error - end - end - end - end -end diff --git a/spec/graphql/mutations/ci/runner/delete_spec.rb b/spec/graphql/mutations/ci/runner/delete_spec.rb index f19fa7c34a9..beff18e1dfd 100644 --- a/spec/graphql/mutations/ci/runner/delete_spec.rb +++ b/spec/graphql/mutations/ci/runner/delete_spec.rb @@ -48,7 +48,7 @@ RSpec.describe Mutations::Ci::Runner::Delete, feature_category: :runner_fleet do let(:mutation_params) { {} } it 'raises an error' do - expect { subject }.to raise_error(ArgumentError, "Arguments must be provided: id") + expect { subject }.to raise_error(ArgumentError, "missing keyword: :id") end end diff --git a/spec/graphql/mutations/ci/runner/update_spec.rb b/spec/graphql/mutations/ci/runner/update_spec.rb index 02bb7ee2170..03bfd4d738b 100644 --- a/spec/graphql/mutations/ci/runner/update_spec.rb +++ b/spec/graphql/mutations/ci/runner/update_spec.rb @@ -42,7 +42,7 @@ RSpec.describe Mutations::Ci::Runner::Update, feature_category: :runner_fleet do let(:mutation_params) { {} } it 'raises an error' do - expect { response }.to raise_error(ArgumentError, "Arguments must be provided: id") + expect { response }.to raise_error(ArgumentError, "missing keyword: :id") end end diff --git a/spec/graphql/mutations/merge_requests/update_spec.rb b/spec/graphql/mutations/merge_requests/update_spec.rb index 6ced71c5f4c..c34ec939d12 100644 --- a/spec/graphql/mutations/merge_requests/update_spec.rb +++ b/spec/graphql/mutations/merge_requests/update_spec.rb @@ -153,20 +153,6 @@ RSpec.describe Mutations::MergeRequests::Update, feature_category: :team_plannin subject(:ready) { mutation.ready?(**arguments) } - context 'when required arguments are not provided' do - let(:arguments) { {} } - - it 'raises an argument error' do - expect { subject }.to raise_error(ArgumentError, 'Arguments must be provided: projectPath, iid') - end - end - - context 'when required arguments are provided' do - it 'returns true' do - expect(subject).to eq(true) - end - end - context 'when timeEstimate is provided' do let(:extra_args) { { time_estimate: time_estimate } } diff --git a/spec/graphql/types/base_argument_spec.rb b/spec/graphql/types/base_argument_spec.rb index 0ce6aa3667d..99154c8c9a5 100644 --- a/spec/graphql/types/base_argument_spec.rb +++ b/spec/graphql/types/base_argument_spec.rb @@ -3,41 +3,14 @@ require 'spec_helper' RSpec.describe Types::BaseArgument, feature_category: :api do - let_it_be(:field) do - Types::BaseField.new(name: 'field', type: String, null: true) - end - - let(:base_args) { { name: 'test', type: String, required: false, owner: field } } - - def subject(args = {}) - described_class.new(**base_args.merge(args)) - end - - include_examples 'Gitlab-style deprecations' - - describe 'required argument declarations' do - it 'accepts nullable, required arguments' do - arguments = base_args.merge({ required: :nullable }) - - expect { subject(arguments) }.not_to raise_error + include_examples 'Gitlab-style deprecations' do + let_it_be(:field) do + Types::BaseField.new(name: 'field', type: String, null: true) end - it 'accepts required, non-nullable arguments' do - arguments = base_args.merge({ required: true }) - - expect { subject(arguments) }.not_to raise_error - end - - it 'accepts non-required arguments' do - arguments = base_args.merge({ required: false }) - - expect { subject(arguments) }.not_to raise_error - end - - it 'accepts no required argument declaration' do - arguments = base_args - - expect { subject(arguments) }.not_to raise_error + def subject(args = {}) + base_args = { name: 'test', type: String, required: false, owner: field } + described_class.new(**base_args.merge(args)) end end end diff --git a/spec/lib/gitlab/ci/yaml_processor/dag_spec.rb b/spec/lib/gitlab/ci/yaml_processor/dag_spec.rb index d688937f997..3c1e0264ff1 100644 --- a/spec/lib/gitlab/ci/yaml_processor/dag_spec.rb +++ b/spec/lib/gitlab/ci/yaml_processor/dag_spec.rb @@ -23,9 +23,19 @@ RSpec.describe Gitlab::Ci::YamlProcessor::Dag do { 'job_a' => %w[job_c], 'job_b' => %w[job_a], 'job_c' => %w[job_b] } end - it 'raises TSort::Cyclic' do + it 'raises TSort::Cyclic error' do expect { result }.to raise_error(TSort::Cyclic, /topological sort failed/) end + + context 'when a job has a self-dependency' do + let(:nodes) do + { 'job_a' => %w[job_a] } + end + + it 'raises TSort::Cyclic error' do + expect { result }.to raise_error(TSort::Cyclic, /topological sort failed/) + end + end end context 'when there are some missing jobs' do diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb index 615a0098a4d..326515883b2 100644 --- a/spec/lib/gitlab/ci/yaml_processor_spec.rb +++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb @@ -3434,6 +3434,23 @@ module Gitlab end it_behaves_like 'returns errors', 'The pipeline has circular dependencies' + + context 'when a job has a self-dependency' do + let(:config) do + <<~YAML + job_0: + stage: test + script: build + + job: + stage: test + script: build + needs: [job_0, job] + YAML + end + + it_behaves_like 'returns errors', 'The pipeline has circular dependencies' + end end end diff --git a/spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb index 7bef14d5f7a..a7dc0b6a060 100644 --- a/spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb +++ b/spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb @@ -113,73 +113,57 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s end end - context 'when usage_ping is disabled' do - it 'does not track the event' do - allow(::ServicePing::ServicePingSettings).to receive(:enabled?).and_return(false) + it 'tracks event when using symbol' do + expect(Gitlab::Redis::HLL).to receive(:add) - described_class.track_event(weekly_event, values: entity1, time: Date.current) - - expect(Gitlab::Redis::HLL).not_to receive(:add) - end + described_class.track_event(:g_analytics_contribution, values: entity1) end - context 'when usage_ping is enabled' do - before do - allow(::ServicePing::ServicePingSettings).to receive(:enabled?).and_return(true) - end + it 'tracks events with multiple values' do + values = [entity1, entity2] + expect(Gitlab::Redis::HLL).to receive(:add).with(key: /g_analytics_contribution/, value: values, + expiry: described_class::KEY_EXPIRY_LENGTH) - it 'tracks event when using symbol' do - expect(Gitlab::Redis::HLL).to receive(:add) - - described_class.track_event(:g_analytics_contribution, values: entity1) - end - - it 'tracks events with multiple values' do - values = [entity1, entity2] - expect(Gitlab::Redis::HLL).to receive(:add).with(key: /g_analytics_contribution/, value: values, - expiry: described_class::KEY_EXPIRY_LENGTH) + described_class.track_event(:g_analytics_contribution, values: values) + end - described_class.track_event(:g_analytics_contribution, values: values) - end + it 'raise error if metrics of unknown event' do + expect { described_class.track_event('unknown', values: entity1, time: Date.current) }.to raise_error(Gitlab::UsageDataCounters::HLLRedisCounter::UnknownEvent) + end - it 'raise error if metrics of unknown event' do - expect { described_class.track_event('unknown', values: entity1, time: Date.current) }.to raise_error(Gitlab::UsageDataCounters::HLLRedisCounter::UnknownEvent) + context 'when Rails environment is production' do + before do + allow(Rails.env).to receive(:development?).and_return(false) + allow(Rails.env).to receive(:test?).and_return(false) end - context 'when Rails environment is production' do - before do - allow(Rails.env).to receive(:development?).and_return(false) - allow(Rails.env).to receive(:test?).and_return(false) - end - - it 'reports only UnknownEvent exception' do - expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception) - .with(Gitlab::UsageDataCounters::HLLRedisCounter::UnknownEvent) - .once - .and_call_original + it 'reports only UnknownEvent exception' do + expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception) + .with(Gitlab::UsageDataCounters::HLLRedisCounter::UnknownEvent) + .once + .and_call_original - expect { described_class.track_event('unknown', values: entity1, time: Date.current) }.not_to raise_error - end + expect { described_class.track_event('unknown', values: entity1, time: Date.current) }.not_to raise_error end + end - it 'reports an error if Feature.enabled raise an error' do - expect(Feature).to receive(:enabled?).and_raise(StandardError.new) - expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception) + it 'reports an error if Feature.enabled raise an error' do + expect(Feature).to receive(:enabled?).and_raise(StandardError.new) + expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception) - described_class.track_event(:g_analytics_contribution, values: entity1, time: Date.current) - end + described_class.track_event(:g_analytics_contribution, values: entity1, time: Date.current) + end - context 'for weekly events' do - it 'sets the keys in Redis to expire' do - described_class.track_event("g_compliance_dashboard", values: entity1) + context 'for weekly events' do + it 'sets the keys in Redis to expire' do + described_class.track_event("g_compliance_dashboard", values: entity1) - Gitlab::Redis::SharedState.with do |redis| - keys = redis.scan_each(match: "{#{described_class::REDIS_SLOT}}_g_compliance_dashboard-*").to_a - expect(keys).not_to be_empty + Gitlab::Redis::SharedState.with do |redis| + keys = redis.scan_each(match: "{#{described_class::REDIS_SLOT}}_g_compliance_dashboard-*").to_a + expect(keys).not_to be_empty - keys.each do |key| - expect(redis.ttl(key)).to be_within(5.seconds).of(described_class::KEY_EXPIRY_LENGTH) - end + keys.each do |key| + expect(redis.ttl(key)).to be_within(5.seconds).of(described_class::KEY_EXPIRY_LENGTH) end end end diff --git a/spec/lib/gitlab/usage_data_counters/redis_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/redis_counter_spec.rb index 753e09731bf..39d48b7b938 100644 --- a/spec/lib/gitlab/usage_data_counters/redis_counter_spec.rb +++ b/spec/lib/gitlab/usage_data_counters/redis_counter_spec.rb @@ -7,51 +7,19 @@ RSpec.describe Gitlab::UsageDataCounters::RedisCounter, :clean_gitlab_redis_shar subject { Class.new.extend(described_class) } - before do - allow(::ServicePing::ServicePingSettings).to receive(:enabled?).and_return(service_ping_enabled) - end - describe '.increment' do - context 'when usage_ping is disabled' do - let(:service_ping_enabled) { false } - - it 'counter is not increased' do - expect do - subject.increment(redis_key) - end.not_to change { subject.total_count(redis_key) } - end - end - - context 'when usage_ping is enabled' do - let(:service_ping_enabled) { true } - - it 'counter is increased' do - expect do - subject.increment(redis_key) - end.to change { subject.total_count(redis_key) }.by(1) - end + it 'counter is increased' do + expect do + subject.increment(redis_key) + end.to change { subject.total_count(redis_key) }.by(1) end end describe '.increment_by' do - context 'when usage_ping is disabled' do - let(:service_ping_enabled) { false } - - it 'counter is not increased' do - expect do - subject.increment_by(redis_key, 3) - end.not_to change { subject.total_count(redis_key) } - end - end - - context 'when usage_ping is enabled' do - let(:service_ping_enabled) { true } - - it 'counter is increased' do - expect do - subject.increment_by(redis_key, 3) - end.to change { subject.total_count(redis_key) }.by(3) - end + it 'counter is increased' do + expect do + subject.increment_by(redis_key, 3) + end.to change { subject.total_count(redis_key) }.by(3) end end end diff --git a/spec/metrics_server/metrics_server_spec.rb b/spec/metrics_server/metrics_server_spec.rb index baf15a773b1..b5e1fb3dbad 100644 --- a/spec/metrics_server/metrics_server_spec.rb +++ b/spec/metrics_server/metrics_server_spec.rb @@ -16,7 +16,7 @@ RSpec.describe MetricsServer, feature_category: :application_performance do # ru before do # Make sure we never actually spawn any new processes in a unit test. - %i(spawn fork detach).each { |m| allow(Process).to receive(m) } + %i[spawn fork detach].each { |m| allow(Process).to receive(m) } # We do not want this to have knock-on effects on the test process. allow(Gitlab::ProcessManagement).to receive(:modify_signals) @@ -33,7 +33,7 @@ RSpec.describe MetricsServer, feature_category: :application_performance do # ru FileUtils.rm_rf(metrics_dir, secure: true) end - %w(puma sidekiq).each do |target| + %w[puma sidekiq].each do |target| context "when targeting #{target}" do describe '.fork' do context 'when in parent process' do diff --git a/spec/models/alert_management/http_integration_spec.rb b/spec/models/alert_management/http_integration_spec.rb index dc26d0323d7..ef9eaa960f2 100644 --- a/spec/models/alert_management/http_integration_spec.rb +++ b/spec/models/alert_management/http_integration_spec.rb @@ -44,8 +44,8 @@ RSpec.describe AlertManagement::HttpIntegration, feature_category: :incident_man context 'with valid JSON schema' do let(:attribute_mapping) do { - title: { path: %w(a b c), type: 'string', label: 'Title' }, - description: { path: %w(a), type: 'string' } + title: { path: %w[a b c], type: 'string', label: 'Title' }, + description: { path: %w[a], type: 'string' } } end @@ -78,7 +78,7 @@ RSpec.describe AlertManagement::HttpIntegration, feature_category: :incident_man context 'when property has extra attributes' do let(:attribute_mapping) do - { title: { path: %w(a b c), type: 'string', extra: 'property' } } + { title: { path: %w[a b c], type: 'string', extra: 'property' } } end it_behaves_like 'is invalid record' diff --git a/spec/models/appearance_spec.rb b/spec/models/appearance_spec.rb index b5f47c950b9..ffb46884e5d 100644 --- a/spec/models/appearance_spec.rb +++ b/spec/models/appearance_spec.rb @@ -81,7 +81,7 @@ RSpec.describe Appearance do end end - %i(logo header_logo pwa_icon favicon).each do |logo_type| + %i[logo header_logo pwa_icon favicon].each do |logo_type| it_behaves_like 'logo paths', logo_type end diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb index 78bf410075b..59701f52f28 100644 --- a/spec/models/application_setting_spec.rb +++ b/spec/models/application_setting_spec.rb @@ -254,11 +254,11 @@ RSpec.describe ApplicationSetting, feature_category: :shared, type: :model do it { is_expected.not_to allow_value(['']).for(:valid_runner_registrars) } it { is_expected.not_to allow_value(['OBVIOUSLY_WRONG']).for(:valid_runner_registrars) } - it { is_expected.not_to allow_value(%w(project project)).for(:valid_runner_registrars) } + it { is_expected.not_to allow_value(%w[project project]).for(:valid_runner_registrars) } it { is_expected.not_to allow_value([nil]).for(:valid_runner_registrars) } it { is_expected.not_to allow_value(nil).for(:valid_runner_registrars) } it { is_expected.to allow_value([]).for(:valid_runner_registrars) } - it { is_expected.to allow_value(%w(project group)).for(:valid_runner_registrars) } + it { is_expected.to allow_value(%w[project group]).for(:valid_runner_registrars) } it { is_expected.to allow_value(http).for(:jira_connect_proxy_url) } it { is_expected.to allow_value(https).for(:jira_connect_proxy_url) } @@ -878,9 +878,9 @@ RSpec.describe ApplicationSetting, feature_category: :shared, type: :model do describe 'inclusion' do it { is_expected.to allow_value('custom1').for(:repository_storages) } - it { is_expected.to allow_value(%w(custom2 custom3)).for(:repository_storages) } + it { is_expected.to allow_value(%w[custom2 custom3]).for(:repository_storages) } it { is_expected.not_to allow_value('alternative').for(:repository_storages) } - it { is_expected.not_to allow_value(%w(alternative custom1)).for(:repository_storages) } + it { is_expected.not_to allow_value(%w[alternative custom1]).for(:repository_storages) } end describe 'presence' do diff --git a/spec/models/authentication_event_spec.rb b/spec/models/authentication_event_spec.rb index 17fe10b5b4e..8ce949c737b 100644 --- a/spec/models/authentication_event_spec.rb +++ b/spec/models/authentication_event_spec.rb @@ -37,11 +37,11 @@ RSpec.describe AuthenticationEvent do describe '.providers' do before do - allow(Devise).to receive(:omniauth_providers).and_return(%w(ldapmain google_oauth2)) + allow(Devise).to receive(:omniauth_providers).and_return(%w[ldapmain google_oauth2]) end it 'returns an array of distinct providers' do - expect(described_class.providers).to match_array %w(ldapmain google_oauth2 standard two-factor two-factor-via-u2f-device two-factor-via-webauthn-device) + expect(described_class.providers).to match_array %w[ldapmain google_oauth2 standard two-factor two-factor-via-u2f-device two-factor-via-webauthn-device] end end diff --git a/spec/models/blob_viewer/base_spec.rb b/spec/models/blob_viewer/base_spec.rb index 682b6dc3b1d..91c32d5c7c9 100644 --- a/spec/models/blob_viewer/base_spec.rb +++ b/spec/models/blob_viewer/base_spec.rb @@ -11,7 +11,7 @@ RSpec.describe BlobViewer::Base do Class.new(described_class) do include BlobViewer::ServerSide - self.extensions = %w(pdf) + self.extensions = %w[pdf] self.binary = true self.collapse_limit = 1.megabyte self.size_limit = 5.megabytes @@ -41,7 +41,7 @@ RSpec.describe BlobViewer::Base do context 'when the file type is supported' do before do - viewer_class.file_types = %i(license) + viewer_class.file_types = %i[license] viewer_class.binary = false end diff --git a/spec/models/ci/build_dependencies_spec.rb b/spec/models/ci/build_dependencies_spec.rb index ab32234eba3..f80af7b9dbc 100644 --- a/spec/models/ci/build_dependencies_spec.rb +++ b/spec/models/ci/build_dependencies_spec.rb @@ -107,7 +107,7 @@ RSpec.describe Ci::BuildDependencies, feature_category: :continuous_integration end context 'when dependencies are defined' do - let(:dependencies) { %w(rspec staging) } + let(:dependencies) { %w[rspec staging] } it { is_expected.to contain_exactly(rspec_test, staging) } end @@ -137,7 +137,7 @@ RSpec.describe Ci::BuildDependencies, feature_category: :continuous_integration end context 'when needs and dependencies are defined' do - let(:dependencies) { %w(rspec staging) } + let(:dependencies) { %w[rspec staging] } let(:needs) do [ { name: 'build', artifacts: true }, @@ -150,7 +150,7 @@ RSpec.describe Ci::BuildDependencies, feature_category: :continuous_integration end context 'when needs and dependencies contradict' do - let(:dependencies) { %w(rspec staging) } + let(:dependencies) { %w[rspec staging] } let(:needs) do [ { name: 'build', artifacts: true }, diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index e2e13ea0e17..19087d00991 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -87,7 +87,7 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def describe 'status' do context 'when transitioning to any state from running' do it 'removes runner_session' do - %w(success drop cancel).each do |event| + %w[success drop cancel].each do |event| build = FactoryBot.create(:ci_build, :running, :with_runner_session, pipeline: pipeline) build.fire_events!(event) @@ -1090,7 +1090,7 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def let(:options_with_fallback_keys) do { cache: [ - { key: "key", paths: ["public"], policy: "pull-push", fallback_keys: %w(key1 key2) } + { key: "key", paths: ["public"], policy: "pull-push", fallback_keys: %w[key1 key2] } ] } end @@ -1111,8 +1111,8 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def let(:options_with_fallback_keys) do { cache: [ - { key: "key", paths: ["public"], policy: "pull-push", fallback_keys: %w(key3 key4) }, - { key: "key2", paths: ["public"], policy: "pull-push", fallback_keys: %w(key5 key6) } + { key: "key", paths: ["public"], policy: "pull-push", fallback_keys: %w[key3 key4] }, + { key: "key2", paths: ["public"], policy: "pull-push", fallback_keys: %w[key5 key6] } ] } end @@ -1214,11 +1214,11 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def is_expected.to match([ a_hash_including({ key: 'key-1', - fallback_keys: %w(key3-1 key4-1) + fallback_keys: %w[key3-1 key4-1] }), a_hash_including({ key: 'key2-1', - fallback_keys: %w(key5-1 key6-1) + fallback_keys: %w[key5-1 key6-1] }) ]) end @@ -1241,11 +1241,11 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def is_expected.to match([ a_hash_including({ key: 'key-1', - fallback_keys: %w(key3-1 key4-1) + fallback_keys: %w[key3-1 key4-1] }), a_hash_including({ key: 'key2-1', - fallback_keys: %w(key5-1 key6-1) + fallback_keys: %w[key5-1 key6-1] }) ]) end @@ -1320,7 +1320,7 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def allow(build).to receive(:options).and_return({ cache: [{ key: "key1", - fallback_keys: %w(key2) + fallback_keys: %w[key2] }] }) end @@ -2951,7 +2951,7 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def end context 'when runner is assigned to build' do - let(:runner) { create(:ci_runner, description: 'description', tag_list: %w(docker linux)) } + let(:runner) { create(:ci_runner, description: 'description', tag_list: %w[docker linux]) } before do build.update!(runner: runner) @@ -3952,8 +3952,8 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def end context 'when have different tags' do - let(:build_tag_list) { %w(A B) } - let(:tag_list) { %w(C D) } + let(:build_tag_list) { %w[A B] } + let(:tag_list) { %w[C D] } it "does not match a build" do is_expected.not_to contain_exactly(build) @@ -3961,8 +3961,8 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def end context 'when have a subset of tags' do - let(:build_tag_list) { %w(A B) } - let(:tag_list) { %w(A B C D) } + let(:build_tag_list) { %w[A B] } + let(:tag_list) { %w[A B C D] } it "does match a build" do is_expected.to contain_exactly(build) @@ -3971,7 +3971,7 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def context 'when build does not have tags' do let(:build_tag_list) { [] } - let(:tag_list) { %w(C D) } + let(:tag_list) { %w[C D] } it "does match a build" do is_expected.to contain_exactly(build) @@ -3979,8 +3979,8 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def end context 'when does not have a subset of tags' do - let(:build_tag_list) { %w(A B C) } - let(:tag_list) { %w(C D) } + let(:build_tag_list) { %w[A B C] } + let(:tag_list) { %w[C D] } it "does not match a build" do is_expected.not_to contain_exactly(build) @@ -3998,7 +3998,7 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def end context 'when does have tags' do - let(:tag_list) { %w(A B) } + let(:tag_list) { %w[A B] } it "does match a build" do is_expected.to contain_exactly(build) @@ -4676,7 +4676,7 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def describe '#invalid_dependencies' do let!(:pre_stage_job_valid) { create(:ci_build, :manual, pipeline: pipeline, name: 'test1', stage_idx: 0) } let!(:pre_stage_job_invalid) { create(:ci_build, :success, :expired, pipeline: pipeline, name: 'test2', stage_idx: 1) } - let!(:job) { create(:ci_build, :pending, pipeline: pipeline, stage_idx: 2, options: { dependencies: %w(test1 test2) }) } + let!(:job) { create(:ci_build, :pending, pipeline: pipeline, stage_idx: 2, options: { dependencies: %w[test1 test2] }) } context 'when pipeline is locked' do before do diff --git a/spec/models/ci/job_artifact_spec.rb b/spec/models/ci/job_artifact_spec.rb index 498af80dbb6..48d46824c11 100644 --- a/spec/models/ci/job_artifact_spec.rb +++ b/spec/models/ci/job_artifact_spec.rb @@ -207,7 +207,7 @@ RSpec.describe Ci::JobArtifact, feature_category: :build_artifacts do subject { described_class.associated_file_types_for(file_type) } where(:file_type, :result) do - 'codequality' | %w(codequality) + 'codequality' | %w[codequality] 'quality' | nil end diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index e0ca7276dc4..9d2c7e876c3 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -1303,7 +1303,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep, feature_category: describe '#stages_names' do it 'returns a valid names of stages' do - expect(pipeline.stages_names).to eq(%w(build test deploy)) + expect(pipeline.stages_names).to eq(%w[build test deploy]) end end end @@ -2640,7 +2640,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep, feature_category: subject(:latest_successful_for_refs) { described_class.latest_successful_for_refs(refs) } context 'when refs are specified' do - let(:refs) { %w(first_ref second_ref third_ref) } + let(:refs) { %w[first_ref second_ref third_ref] } before do create(:ci_empty_pipeline, id: 1001, status: :success, ref: 'first_ref', sha: 'sha') diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb index 538eb51387e..bb9ac084ed6 100644 --- a/spec/models/ci/runner_spec.rb +++ b/spec/models/ci/runner_spec.rb @@ -772,7 +772,7 @@ RSpec.describe Ci::Runner, type: :model, feature_category: :runner do end context 'when runner has tags' do - let(:tag_list) { %w(bb cc) } + let(:tag_list) { %w[bb cc] } shared_examples 'tagged build picker' do it 'can handle build with matching tags' do diff --git a/spec/models/clusters/agent_spec.rb b/spec/models/clusters/agent_spec.rb index 6201b7b1861..062d5062658 100644 --- a/spec/models/clusters/agent_spec.rb +++ b/spec/models/clusters/agent_spec.rb @@ -21,7 +21,7 @@ RSpec.describe Clusters::Agent, feature_category: :deployment_management do describe 'scopes' do describe '.ordered_by_name' do - let(:names) { %w(agent-d agent-b agent-a agent-c) } + let(:names) { %w[agent-d agent-b agent-a agent-c] } subject { described_class.ordered_by_name } diff --git a/spec/models/clusters/platforms/kubernetes_spec.rb b/spec/models/clusters/platforms/kubernetes_spec.rb index c32abaf50f5..79a81977611 100644 --- a/spec/models/clusters/platforms/kubernetes_spec.rb +++ b/spec/models/clusters/platforms/kubernetes_spec.rb @@ -10,7 +10,7 @@ RSpec.describe Clusters::Platforms::Kubernetes do it { is_expected.to be_kind_of(Gitlab::Kubernetes) } it { is_expected.to respond_to :ca_pem } - it { is_expected.to validate_exclusion_of(:namespace).in_array(%w(gitlab-managed-apps)) } + it { is_expected.to validate_exclusion_of(:namespace).in_array(%w[gitlab-managed-apps]) } it { is_expected.to validate_presence_of(:api_url) } it { is_expected.to validate_presence_of(:token) } diff --git a/spec/models/commit_range_spec.rb b/spec/models/commit_range_spec.rb index 334833e884b..fe8c28d7251 100644 --- a/spec/models/commit_range_spec.rb +++ b/spec/models/commit_range_spec.rb @@ -77,7 +77,7 @@ RSpec.describe CommitRange do describe '#to_param' do it 'includes the correct keys' do - expect(range.to_param.keys).to eq %i(from to) + expect(range.to_param.keys).to eq %i[from to] end it 'includes the correct values for a three-dot range' do diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb index 7ab43611108..f9885d9081e 100644 --- a/spec/models/commit_spec.rb +++ b/spec/models/commit_spec.rb @@ -23,13 +23,13 @@ RSpec.describe Commit do shared_examples '.lazy checks' do context 'when the commits are found' do let(:oids) do - %w( + %w[ 498214de67004b1da3d820901307bed2a68a8ef6 c642fe9b8b9f28f9225d7ea953fe14e74748d53b 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9 048721d90c449b244b7b4c53a9186b04330174ec 281d3a76f31c812dbf48abce82ccf6860adedd81 - ) + ] end subject { oids.map { |oid| described_class.lazy(container, oid) } } diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb index 9371fde4d4b..618dd3a3f77 100644 --- a/spec/models/commit_status_spec.rb +++ b/spec/models/commit_status_spec.rb @@ -27,7 +27,7 @@ RSpec.describe CommitStatus, feature_category: :continuous_integration do it { is_expected.to belong_to(:auto_canceled_by) } it { is_expected.to validate_presence_of(:name) } - it { is_expected.to validate_inclusion_of(:status).in_array(%w(pending running failed success canceled)) } + it { is_expected.to validate_inclusion_of(:status).in_array(%w[pending running failed success canceled]) } it { is_expected.to validate_length_of(:stage).is_at_most(255) } it { is_expected.to validate_length_of(:ref).is_at_most(255) } diff --git a/spec/models/compare_spec.rb b/spec/models/compare_spec.rb index 2206ed7bfe8..78610d002b2 100644 --- a/spec/models/compare_spec.rb +++ b/spec/models/compare_spec.rb @@ -129,13 +129,13 @@ RSpec.describe Compare, feature_category: :source_code_management do it 'returns affected file paths, without duplication' do expect(subject.modified_paths).to contain_exactly( - *%w{ + *%w[ foo/for_move.txt foo/bar/for_move.txt foo/for_create.txt foo/for_delete.txt foo/for_edit.txt - }) + ]) end end diff --git a/spec/models/concerns/awardable_spec.rb b/spec/models/concerns/awardable_spec.rb index fcd0d0c05f4..828b75aceb0 100644 --- a/spec/models/concerns/awardable_spec.rb +++ b/spec/models/concerns/awardable_spec.rb @@ -102,7 +102,7 @@ RSpec.describe Awardable do end it "includes unused thumbs buttons by default" do - expect(note_without_downvote.grouped_awards.keys.sort).to eq %w(thumbsdown thumbsup) + expect(note_without_downvote.grouped_awards.keys.sort).to eq %w[thumbsdown thumbsup] end it "doesn't include unused thumbs buttons when disabled in project" do @@ -114,7 +114,7 @@ RSpec.describe Awardable do it "includes unused thumbs buttons when enabled in project" do note_without_downvote.project.show_default_award_emojis = true - expect(note_without_downvote.grouped_awards.keys.sort).to eq %w(thumbsdown thumbsup) + expect(note_without_downvote.grouped_awards.keys.sort).to eq %w[thumbsdown thumbsup] end it "doesn't include unused thumbs buttons in summary" do @@ -124,11 +124,11 @@ RSpec.describe Awardable do it "includes used thumbs buttons when disabled in project" do note_with_downvote.project.show_default_award_emojis = false - expect(note_with_downvote.grouped_awards.keys).to eq %w(thumbsdown) + expect(note_with_downvote.grouped_awards.keys).to eq %w[thumbsdown] end it "includes used thumbs buttons in summary" do - expect(note_with_downvote.grouped_awards(with_thumbs: false).keys).to eq %w(thumbsdown) + expect(note_with_downvote.grouped_awards(with_thumbs: false).keys).to eq %w[thumbsdown] end end end diff --git a/spec/models/concerns/case_sensitivity_spec.rb b/spec/models/concerns/case_sensitivity_spec.rb index 6e624c687c4..a8e52904873 100644 --- a/spec/models/concerns/case_sensitivity_spec.rb +++ b/spec/models/concerns/case_sensitivity_spec.rb @@ -21,11 +21,11 @@ RSpec.describe CaseSensitivity do end it 'finds multiple instances by a single attribute regardless of case' do - expect(model.iwhere(path: %w(MODEL-1 model-2))).to contain_exactly(model_1, model_2) + expect(model.iwhere(path: %w[MODEL-1 model-2])).to contain_exactly(model_1, model_2) end it 'finds instances by multiple attributes' do - expect(model.iwhere(path: %w(MODEL-1 model-2), name: 'model 1')) + expect(model.iwhere(path: %w[MODEL-1 model-2], name: 'model 1')) .to contain_exactly(model_1) end @@ -34,7 +34,7 @@ RSpec.describe CaseSensitivity do end it 'builds a query using LOWER' do - query = model.iwhere(path: %w(MODEL-1 model-2), name: 'model 1').to_sql + query = model.iwhere(path: %w[MODEL-1 model-2], name: 'model 1').to_sql expected_query = <<~QRY.strip SELECT \"namespaces\".* FROM \"namespaces\" WHERE (LOWER(\"namespaces\".\"path\") IN (LOWER('MODEL-1'), LOWER('model-2'))) AND (LOWER(\"namespaces\".\"name\") = LOWER('model 1')) QRY diff --git a/spec/models/concerns/featurable_spec.rb b/spec/models/concerns/featurable_spec.rb index bf104fe1b30..97ad4fc8bdd 100644 --- a/spec/models/concerns/featurable_spec.rb +++ b/spec/models/concerns/featurable_spec.rb @@ -9,7 +9,7 @@ RSpec.describe Featurable do self.table_name = 'project_features' - set_available_features %i(feature1 feature2 feature3) + set_available_features %i[feature1 feature2 feature3] def feature1_access_level Featurable::DISABLED diff --git a/spec/models/concerns/ignorable_columns_spec.rb b/spec/models/concerns/ignorable_columns_spec.rb index c97dc606159..339f06f9c45 100644 --- a/spec/models/concerns/ignorable_columns_spec.rb +++ b/spec/models/concerns/ignorable_columns_spec.rb @@ -14,13 +14,13 @@ RSpec.describe IgnorableColumns do it 'adds columns to ignored_columns' do expect do subject.ignore_columns(:name, :created_at, remove_after: '2019-12-01', remove_with: '12.6') - end.to change { subject.ignored_columns }.from([]).to(%w(name created_at)) + end.to change { subject.ignored_columns }.from([]).to(%w[name created_at]) end it 'adds columns to ignored_columns (array version)' do expect do subject.ignore_columns(%i[name created_at], remove_after: '2019-12-01', remove_with: '12.6') - end.to change { subject.ignored_columns }.from([]).to(%w(name created_at)) + end.to change { subject.ignored_columns }.from([]).to(%w[name created_at]) end it 'requires remove_after attribute to be set' do diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb index 705f8f46a90..d61a465b39f 100644 --- a/spec/models/concerns/issuable_spec.rb +++ b/spec/models/concerns/issuable_spec.rb @@ -597,7 +597,7 @@ RSpec.describe Issuable, feature_category: :team_planning do expect(builder).to receive(:build).with( user: user, changes: hash_including( - 'severity' => %w(unknown low) + 'severity' => %w[unknown low] )) issue.to_hook_data(user, old_associations: { severity: 'unknown' }) @@ -618,7 +618,7 @@ RSpec.describe Issuable, feature_category: :team_planning do expect(builder).to receive(:build).with( user: user, changes: hash_including( - 'escalation_status' => %i(triggered acknowledged) + 'escalation_status' => %i[triggered acknowledged] )) issue.to_hook_data(user, old_associations: { escalation_status: :triggered }) diff --git a/spec/models/concerns/pg_full_text_searchable_spec.rb b/spec/models/concerns/pg_full_text_searchable_spec.rb index 059df64f7d0..8e3b65cf125 100644 --- a/spec/models/concerns/pg_full_text_searchable_spec.rb +++ b/spec/models/concerns/pg_full_text_searchable_spec.rb @@ -18,7 +18,7 @@ RSpec.describe PgFullTextSearchable, feature_category: :global_search do before_validation -> { self.work_item_type_id = ::WorkItems::Type.default_issue_type.id } def persist_pg_full_text_search_vector(search_vector) - Issues::SearchData.upsert({ project_id: project_id, issue_id: id, search_vector: search_vector }, unique_by: %i(project_id issue_id)) + Issues::SearchData.upsert({ project_id: project_id, issue_id: id, search_vector: search_vector }, unique_by: %i[project_id issue_id]) end def self.name @@ -95,7 +95,7 @@ RSpec.describe PgFullTextSearchable, feature_category: :global_search do matching_object = model_class.create!(project: project, namespace: project.project_namespace, title: 'english', description: 'some description') matching_object.update_search_data! - expect(model_class.pg_full_text_search('english', matched_columns: %w(title))).to contain_exactly(matching_object) + expect(model_class.pg_full_text_search('english', matched_columns: %w[title])).to contain_exactly(matching_object) end it 'uses prefix matching' do diff --git a/spec/models/concerns/project_features_compatibility_spec.rb b/spec/models/concerns/project_features_compatibility_spec.rb index f168bedc8eb..46390fa735b 100644 --- a/spec/models/concerns/project_features_compatibility_spec.rb +++ b/spec/models/concerns/project_features_compatibility_spec.rb @@ -4,12 +4,12 @@ require 'spec_helper' RSpec.describe ProjectFeaturesCompatibility do let(:project) { create(:project) } - let(:features_enabled) { %w(issues wiki builds merge_requests snippets security_and_compliance) } + let(:features_enabled) { %w[issues wiki builds merge_requests snippets security_and_compliance] } let(:features) do - features_enabled + %w( + features_enabled + %w[ repository pages operations container_registry package_registry environments feature_flags releases monitor infrastructure - ) + ] end # We had issues_enabled, snippets_enabled, builds_enabled, merge_requests_enabled and issues_enabled fields on projects table diff --git a/spec/models/concerns/reactive_caching_spec.rb b/spec/models/concerns/reactive_caching_spec.rb index 039b9e574fe..324759fc7ee 100644 --- a/spec/models/concerns/reactive_caching_spec.rb +++ b/spec/models/concerns/reactive_caching_spec.rb @@ -176,7 +176,7 @@ RSpec.describe ReactiveCaching, :use_clean_rails_memory_store_caching do describe '.reactive_cache_worker_finder' do context 'with default reactive_cache_worker_finder' do - let(:args) { %w(other args) } + let(:args) { %w[other args] } before do allow(instance.class).to receive(:find_by).with(id: instance.id) @@ -192,7 +192,7 @@ RSpec.describe ReactiveCaching, :use_clean_rails_memory_store_caching do end context 'with custom reactive_cache_worker_finder' do - let(:args) { %w(arg1 arg2) } + let(:args) { %w[arg1 arg2] } let(:instance) { custom_finder_cache_test.new(666, &calculation) } let(:custom_finder_cache_test) do diff --git a/spec/models/concerns/sortable_spec.rb b/spec/models/concerns/sortable_spec.rb index f1ae89f33af..98f4ab4f521 100644 --- a/spec/models/concerns/sortable_spec.rb +++ b/spec/models/concerns/sortable_spec.rb @@ -14,14 +14,14 @@ RSpec.describe Sortable do it 'allows secondary ordering by id ascending' do orders = arel_orders(sorted_relation.with_order_id_asc) - expect(orders.map { |arel| arel.expr.name }).to eq(%w(created_at id)) + expect(orders.map { |arel| arel.expr.name }).to eq(%w[created_at id]) expect(orders).to all(be_kind_of(Arel::Nodes::Ascending)) end it 'allows secondary ordering by id descending' do orders = arel_orders(sorted_relation.with_order_id_desc) - expect(orders.map { |arel| arel.expr.name }).to eq(%w(created_at id)) + expect(orders.map { |arel| arel.expr.name }).to eq(%w[created_at id]) expect(orders.first).to be_kind_of(Arel::Nodes::Ascending) expect(orders.last).to be_kind_of(Arel::Nodes::Descending) end @@ -123,24 +123,24 @@ RSpec.describe Sortable do let!(:group4) { create(:group, name: 'bbb', id: 4, created_at: ref_time, updated_at: ref_time - 15.seconds) } it 'sorts groups by id' do - expect(ordered_group_names('id_asc')).to eq(%w(aa AAA BB bbb)) - expect(ordered_group_names('id_desc')).to eq(%w(bbb BB AAA aa)) + expect(ordered_group_names('id_asc')).to eq(%w[aa AAA BB bbb]) + expect(ordered_group_names('id_desc')).to eq(%w[bbb BB AAA aa]) end it 'sorts groups by name via case-insensitive comparision' do - expect(ordered_group_names('name_asc')).to eq(%w(aa AAA BB bbb)) - expect(ordered_group_names('name_desc')).to eq(%w(bbb BB AAA aa)) + expect(ordered_group_names('name_asc')).to eq(%w[aa AAA BB bbb]) + expect(ordered_group_names('name_desc')).to eq(%w[bbb BB AAA aa]) end it 'sorts groups by created_at' do - expect(ordered_group_names('created_asc')).to eq(%w(aa AAA BB bbb)) - expect(ordered_group_names('created_desc')).to eq(%w(bbb BB AAA aa)) - expect(ordered_group_names('created_date')).to eq(%w(bbb BB AAA aa)) + expect(ordered_group_names('created_asc')).to eq(%w[aa AAA BB bbb]) + expect(ordered_group_names('created_desc')).to eq(%w[bbb BB AAA aa]) + expect(ordered_group_names('created_date')).to eq(%w[bbb BB AAA aa]) end it 'sorts groups by updated_at' do - expect(ordered_group_names('updated_asc')).to eq(%w(bbb BB AAA aa)) - expect(ordered_group_names('updated_desc')).to eq(%w(aa AAA BB bbb)) + expect(ordered_group_names('updated_asc')).to eq(%w[bbb BB AAA aa]) + expect(ordered_group_names('updated_desc')).to eq(%w[aa AAA BB bbb]) end end end diff --git a/spec/models/deployment_spec.rb b/spec/models/deployment_spec.rb index 639b149e2ae..ee48e8cac6c 100644 --- a/spec/models/deployment_spec.rb +++ b/spec/models/deployment_spec.rb @@ -1336,7 +1336,7 @@ RSpec.describe Deployment, feature_category: :continuous_delivery do let(:job_status) { :created } it_behaves_like 'gracefully handling error' do - let(:error_message) { %{Status cannot transition via \"create\"} } + let(:error_message) { %(Status cannot transition via \"create\") } end end @@ -1344,7 +1344,7 @@ RSpec.describe Deployment, feature_category: :continuous_delivery do let(:job_status) { :manual } it_behaves_like 'gracefully handling error' do - let(:error_message) { %{Status cannot transition via \"block\"} } + let(:error_message) { %(Status cannot transition via \"block\") } end end @@ -1374,7 +1374,7 @@ RSpec.describe Deployment, feature_category: :continuous_delivery do let(:job_status) { :created } it_behaves_like 'gracefully handling error' do - let(:error_message) { %{Status cannot transition via \"create\"} } + let(:error_message) { %(Status cannot transition via \"create\") } end end @@ -1382,7 +1382,7 @@ RSpec.describe Deployment, feature_category: :continuous_delivery do let(:job_status) { :manual } it_behaves_like 'gracefully handling error' do - let(:error_message) { %{Status cannot transition via \"block\"} } + let(:error_message) { %(Status cannot transition via \"block\") } end end @@ -1390,7 +1390,7 @@ RSpec.describe Deployment, feature_category: :continuous_delivery do let(:job_status) { :running } it_behaves_like 'gracefully handling error' do - let(:error_message) { %{Status cannot transition via \"run\"} } + let(:error_message) { %(Status cannot transition via \"run\") } end end diff --git a/spec/models/diff_viewer/base_spec.rb b/spec/models/diff_viewer/base_spec.rb index 57c62788ee9..8ab7b090928 100644 --- a/spec/models/diff_viewer/base_spec.rb +++ b/spec/models/diff_viewer/base_spec.rb @@ -13,7 +13,7 @@ RSpec.describe DiffViewer::Base do Class.new(described_class) do include DiffViewer::ServerSide - self.extensions = %w(jpg) + self.extensions = %w[jpg] self.binary = true self.collapse_limit = 1.megabyte self.size_limit = 5.megabytes @@ -55,7 +55,7 @@ RSpec.describe DiffViewer::Base do before do allow(diff_file).to receive(:renamed_file?).and_return(true) - viewer_class.extensions = %w(notjpg) + viewer_class.extensions = %w[notjpg] end it 'returns false' do diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb index dcfee7fcc8c..9cf82c707f1 100644 --- a/spec/models/environment_spec.rb +++ b/spec/models/environment_spec.rb @@ -1361,7 +1361,7 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching, feature_categ end context 'reactive cache has pod data' do - let(:cache_data) { Hash(pods: %w(pod1 pod2)) } + let(:cache_data) { Hash(pods: %w[pod1 pod2]) } before do stub_reactive_cache(environment, cache_data) @@ -1390,9 +1390,9 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching, feature_categ it 'returns cache data from the deployment platform' do expect(environment.deployment_platform).to receive(:calculate_reactive_cache_for) - .with(environment).and_return(pods: %w(pod1 pod2)) + .with(environment).and_return(pods: %w[pod1 pod2]) - is_expected.to eq(pods: %w(pod1 pod2)) + is_expected.to eq(pods: %w[pod1 pod2]) end context 'environment does not have terminals available' do @@ -1863,8 +1863,8 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching, feature_categ end context 'cached rollout status is present' do - let(:pods) { %w(pod1 pod2) } - let(:deployments) { %w(deployment1 deployment2) } + let(:pods) { %w[pod1 pod2] } + let(:deployments) { %w[deployment1 deployment2] } before do stub_reactive_cache(environment, pods: pods, deployments: deployments) diff --git a/spec/models/group_label_spec.rb b/spec/models/group_label_spec.rb index 701348baf48..40019fdc94c 100644 --- a/spec/models/group_label_spec.rb +++ b/spec/models/group_label_spec.rb @@ -34,7 +34,7 @@ RSpec.describe GroupLabel do end it 'uses id when name contains double quote' do - label = create(:label, name: %q{"irony"}) + label = create(:label, name: %q("irony")) expect(label.to_reference(format: :name)).to eq "~#{label.id}" end end diff --git a/spec/models/instance_configuration_spec.rb b/spec/models/instance_configuration_spec.rb index 346f743e8ef..6fbb9245885 100644 --- a/spec/models/instance_configuration_spec.rb +++ b/spec/models/instance_configuration_spec.rb @@ -36,7 +36,7 @@ RSpec.describe InstanceConfiguration do result = subject.settings[:ssh_algorithms_hashes] - expect(result.map { |a| a[:name] }).to match_array(%w(DSA ECDSA ED25519 RSA)) + expect(result.map { |a| a[:name] }).to match_array(%w[DSA ECDSA ED25519 RSA]) end it 'does not include disabled algorithm' do @@ -45,7 +45,7 @@ RSpec.describe InstanceConfiguration do result = subject.settings[:ssh_algorithms_hashes] - expect(result.map { |a| a[:name] }).to match_array(%w(ECDSA ED25519 RSA)) + expect(result.map { |a| a[:name] }).to match_array(%w[ECDSA ED25519 RSA]) end def pub_file(exist: true) diff --git a/spec/models/integration_spec.rb b/spec/models/integration_spec.rb index 8396d5469ad..75f74f61bde 100644 --- a/spec/models/integration_spec.rb +++ b/spec/models/integration_spec.rb @@ -988,7 +988,7 @@ RSpec.describe Integration, feature_category: :integrations do subject { described_class.available_integration_names } before do - allow(described_class).to receive(:integration_names).and_return(%w(foo)) + allow(described_class).to receive(:integration_names).and_return(%w[foo]) allow(described_class).to receive(:project_specific_integration_names).and_return(['bar']) allow(described_class).to receive(:dev_integration_names).and_return(['baz']) end diff --git a/spec/models/integrations/buildkite_spec.rb b/spec/models/integrations/buildkite_spec.rb index f3231d50eae..ce31c0b20a3 100644 --- a/spec/models/integrations/buildkite_spec.rb +++ b/spec/models/integrations/buildkite_spec.rb @@ -50,7 +50,7 @@ RSpec.describe Integrations::Buildkite, :use_clean_rails_memory_store_caching, f describe '.supported_events' do it 'supports push, merge_request, and tag_push events' do - expect(integration.supported_events).to eq %w(push merge_request tag_push) + expect(integration.supported_events).to eq %w[push merge_request tag_push] end end diff --git a/spec/models/integrations/campfire_spec.rb b/spec/models/integrations/campfire_spec.rb index 38d3d89cdbf..19f819252f8 100644 --- a/spec/models/integrations/campfire_spec.rb +++ b/spec/models/integrations/campfire_spec.rb @@ -48,7 +48,7 @@ RSpec.describe Integrations::Campfire, feature_category: :integrations do ) @sample_data = Gitlab::DataBuilder::Push.build_sample(project, user) @rooms_url = 'https://project-name.campfirenow.com/rooms.json' - @auth = %w(verySecret X) + @auth = %w[verySecret X] @headers = { 'Content-Type' => 'application/json; charset=utf-8' } end diff --git a/spec/models/integrations/jira_spec.rb b/spec/models/integrations/jira_spec.rb index c87128db221..d3ae92ea52a 100644 --- a/spec/models/integrations/jira_spec.rb +++ b/spec/models/integrations/jira_spec.rb @@ -719,10 +719,10 @@ RSpec.describe Integrations::Jira, feature_category: :integrations do allow_any_instance_of(JIRA::Resource::Issue).to receive(:key).and_return(issue_key) allow(JIRA::Resource::Remotelink).to receive(:all).and_return([]) - WebMock.stub_request(:get, issue_url).with(basic_auth: %w(jira-username jira-password)) - WebMock.stub_request(:post, transitions_url).with(basic_auth: %w(jira-username jira-password)) - WebMock.stub_request(:post, comment_url).with(basic_auth: %w(jira-username jira-password)) - WebMock.stub_request(:post, remote_link_url).with(basic_auth: %w(jira-username jira-password)) + WebMock.stub_request(:get, issue_url).with(basic_auth: %w[jira-username jira-password]) + WebMock.stub_request(:post, transitions_url).with(basic_auth: %w[jira-username jira-password]) + WebMock.stub_request(:post, comment_url).with(basic_auth: %w[jira-username jira-password]) + WebMock.stub_request(:post, remote_link_url).with(basic_auth: %w[jira-username jira-password]) end let(:external_issue) { ExternalIssue.new('JIRA-123', project) } @@ -864,7 +864,7 @@ RSpec.describe Integrations::Jira, feature_category: :integrations do it 'logs exception when transition id is not valid' do allow(jira_integration).to receive(:log_exception) - WebMock.stub_request(:post, transitions_url).with(basic_auth: %w(jira-username jira-password)).and_raise("Bad Request") + WebMock.stub_request(:post, transitions_url).with(basic_auth: %w[jira-username jira-password]).and_raise("Bad Request") close_issue @@ -973,7 +973,7 @@ RSpec.describe Integrations::Jira, feature_category: :integrations do context 'when a transition fails' do before do - WebMock.stub_request(:post, transitions_url).with(basic_auth: %w(jira-username jira-password)).to_return do |request| + WebMock.stub_request(:post, transitions_url).with(basic_auth: %w[jira-username jira-password]).to_return do |request| { status: request.body.include?('"id":"2"') ? 500 : 200 } end end diff --git a/spec/models/integrations/teamcity_spec.rb b/spec/models/integrations/teamcity_spec.rb index c4c7202fae0..1537b10ba03 100644 --- a/spec/models/integrations/teamcity_spec.rb +++ b/spec/models/integrations/teamcity_spec.rb @@ -308,7 +308,7 @@ RSpec.describe Integrations::Teamcity, :use_clean_rails_memory_store_caching do def stub_post_to_build_queue(branch:) teamcity_full_url = "#{teamcity_url}/httpAuth/app/rest/buildQueue" body ||= %() - auth = %w(mic password) + auth = %w[mic password] stub_full_request(teamcity_full_url, method: :post).with( basic_auth: auth, @@ -320,7 +320,7 @@ RSpec.describe Integrations::Teamcity, :use_clean_rails_memory_store_caching do end def stub_request(status: 200, body: nil, build_status: 'success') - auth = %w(mic password) + auth = %w[mic password] body ||= %({"build":{"status":"#{build_status}","id":"666"}}) diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb index e7a5a53c6a0..6c8603d7b4c 100644 --- a/spec/models/issue_spec.rb +++ b/spec/models/issue_spec.rb @@ -373,10 +373,10 @@ RSpec.describe Issue, feature_category: :team_planning do describe '.simple_sorts' do it 'includes all keys' do expect(described_class.simple_sorts.keys).to include( - *%w(created_asc created_at_asc created_date created_desc created_at_desc + *%w[created_asc created_at_asc created_date created_desc created_at_desc closest_future_date closest_future_date_asc due_date due_date_asc due_date_desc id_asc id_desc relative_position relative_position_asc updated_desc updated_asc - updated_at_asc updated_at_desc title_asc title_desc)) + updated_at_asc updated_at_desc title_asc title_desc]) end end @@ -390,7 +390,7 @@ RSpec.describe Issue, feature_category: :team_planning do end it 'returns issues with the given issue types' do - expect(described_class.with_issue_type(%w(issue incident))) + expect(described_class.with_issue_type(%w[issue incident])) .to contain_exactly(issue, incident) end @@ -439,7 +439,7 @@ RSpec.describe Issue, feature_category: :team_planning do end it 'returns issues without the given issue types' do - expect(described_class.without_issue_type(%w(issue incident))) + expect(described_class.without_issue_type(%w[issue incident])) .to contain_exactly(task) end diff --git a/spec/models/merge_request_diff_spec.rb b/spec/models/merge_request_diff_spec.rb index 806ce3f21b5..bcab2029942 100644 --- a/spec/models/merge_request_diff_spec.rb +++ b/spec/models/merge_request_diff_spec.rb @@ -1090,7 +1090,7 @@ RSpec.describe MergeRequestDiff, feature_category: :code_review_workflow do end it 'returns affected file paths' do - expect(subject.modified_paths).to eq(%w{foo bar baz}) + expect(subject.modified_paths).to eq(%w[foo bar baz]) end context "when fallback_on_overflow is true" do diff --git a/spec/models/namespace_statistics_spec.rb b/spec/models/namespace_statistics_spec.rb index ac747b70a9f..ee3b4765dba 100644 --- a/spec/models/namespace_statistics_spec.rb +++ b/spec/models/namespace_statistics_spec.rb @@ -171,7 +171,7 @@ RSpec.describe NamespaceStatistics do context 'when other columns are updated' do it 'does not enqueue the job to update root storage statistics' do - columns_to_update = NamespaceStatistics.columns_hash.reject { |k, _| %w(id namespace_id).include?(k) || k.include?('_size') }.keys + columns_to_update = NamespaceStatistics.columns_hash.reject { |k, _| %w[id namespace_id].include?(k) || k.include?('_size') }.keys columns_to_update.each { |c| statistics[c] = 10 } expect(statistics).not_to receive(:update_root_storage_statistics) diff --git a/spec/models/packages/package_spec.rb b/spec/models/packages/package_spec.rb index e113218e828..8e3b97e55f3 100644 --- a/spec/models/packages/package_spec.rb +++ b/spec/models/packages/package_spec.rb @@ -1196,7 +1196,7 @@ RSpec.describe Packages::Package, type: :model, feature_category: :package_regis it { is_expected.to eq([]) } context 'with tags' do - let(:tags) { %w(tag1 tag2 tag3) } + let(:tags) { %w[tag1 tag2 tag3] } before do tags.each { |t| create(:packages_tag, name: t, package: package) } diff --git a/spec/models/packages/tag_spec.rb b/spec/models/packages/tag_spec.rb index bc03c34f56b..8a6b88f966d 100644 --- a/spec/models/packages/tag_spec.rb +++ b/spec/models/packages/tag_spec.rb @@ -61,7 +61,7 @@ RSpec.describe Packages::Tag, type: :model, feature_category: :package_registry end context 'with multiple names' do - let(:name) { %w(tag1 tag3) } + let(:name) { %w[tag1 tag3] } it { is_expected.to contain_exactly(tag1, tag3) } end diff --git a/spec/models/pages_domain_spec.rb b/spec/models/pages_domain_spec.rb index 5a4eca11f71..fae0b9d011c 100644 --- a/spec/models/pages_domain_spec.rb +++ b/spec/models/pages_domain_spec.rb @@ -84,20 +84,20 @@ RSpec.describe PagesDomain, feature_category: :pages do attributes = attributes_for(:pages_domain) cert, key = attributes.fetch_values(:certificate, :key) - true | nil | nil | false | %i(certificate key) + true | nil | nil | false | %i[certificate key] true | nil | nil | true | [] - true | cert | nil | false | %i(key) - true | cert | nil | true | %i(key) - true | nil | key | false | %i(certificate key) - true | nil | key | true | %i(key) + true | cert | nil | false | %i[key] + true | cert | nil | true | %i[key] + true | nil | key | false | %i[certificate key] + true | nil | key | true | %i[key] true | cert | key | false | [] true | cert | key | true | [] false | nil | nil | false | [] false | nil | nil | true | [] - false | cert | nil | false | %i(key) - false | cert | nil | true | %i(key) - false | nil | key | false | %i(key) - false | nil | key | true | %i(key) + false | cert | nil | false | %i[key] + false | cert | nil | true | %i[key] + false | nil | key | false | %i[key] + false | nil | key | true | %i[key] false | cert | key | false | [] false | cert | key | true | [] end diff --git a/spec/models/personal_access_token_spec.rb b/spec/models/personal_access_token_spec.rb index 7437e9b463e..7665f4dbde4 100644 --- a/spec/models/personal_access_token_spec.rb +++ b/spec/models/personal_access_token_spec.rb @@ -365,7 +365,7 @@ RSpec.describe PersonalAccessToken, feature_category: :system_access do describe '.simple_sorts' do it 'includes overridden keys' do - expect(described_class.simple_sorts.keys).to include(*%w(expires_at_asc_id_desc)) + expect(described_class.simple_sorts.keys).to include(*%w[expires_at_asc_id_desc]) end end diff --git a/spec/models/project_feature_spec.rb b/spec/models/project_feature_spec.rb index 39e77df1900..c0a78ff2f53 100644 --- a/spec/models/project_feature_spec.rb +++ b/spec/models/project_feature_spec.rb @@ -53,7 +53,7 @@ RSpec.describe ProjectFeature, feature_category: :groups_and_projects do end it "does not allow repository related features have higher level" do - features = %w(builds merge_requests) + features = %w[builds merge_requests] project_feature = project.project_feature features.each do |feature| @@ -64,7 +64,7 @@ RSpec.describe ProjectFeature, feature_category: :groups_and_projects do end end - it_behaves_like 'access level validation', ProjectFeature::FEATURES - %i(pages package_registry) do + it_behaves_like 'access level validation', ProjectFeature::FEATURES - %i[pages package_registry] do let(:container_features) { project.project_feature } end diff --git a/spec/models/project_label_spec.rb b/spec/models/project_label_spec.rb index 62839f5fb4f..01df58ee615 100644 --- a/spec/models/project_label_spec.rb +++ b/spec/models/project_label_spec.rb @@ -89,7 +89,7 @@ RSpec.describe ProjectLabel do end it 'uses id when name contains double quote' do - label = create(:label, name: %q{"irony"}) + label = create(:label, name: %q("irony")) expect(label.to_reference(format: :name)).to eq "~#{label.id}" end end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index d4e23823f23..5f1054a35bb 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -1136,24 +1136,24 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr it { is_expected.to delegate_method(:npm_package_requests_forwarding).to(:namespace) } describe 'read project settings' do - %i( + %i[ show_default_award_emojis show_default_award_emojis? warn_about_potentially_unwanted_characters warn_about_potentially_unwanted_characters? enforce_auth_checks_on_uploads enforce_auth_checks_on_uploads? - ).each do |method| + ].each do |method| it { is_expected.to delegate_method(method).to(:project_setting).allow_nil } end end describe 'write project settings' do - %i( + %i[ show_default_award_emojis= warn_about_potentially_unwanted_characters= enforce_auth_checks_on_uploads= - ).each do |method| + ].each do |method| it { is_expected.to delegate_method(method).to(:project_setting).with_arguments(:args).allow_nil } end end @@ -1177,12 +1177,12 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr let(:exclude_attributes) do # Skip attributes defined in EE code - %w( + %w[ merge_pipelines_enabled merge_trains_enabled auto_rollback_enabled merge_trains_skip_train_allowed - ) + ] end end @@ -4287,7 +4287,7 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr end context 'when project has a deployment platform' do - let(:platform_variables) { %w(platform variables) } + let(:platform_variables) { %w[platform variables] } let(:deployment_platform) { double } before do diff --git a/spec/models/projects/topic_spec.rb b/spec/models/projects/topic_spec.rb index 568a4166de7..b3a55ccd370 100644 --- a/spec/models/projects/topic_spec.rb +++ b/spec/models/projects/topic_spec.rb @@ -76,7 +76,7 @@ RSpec.describe Projects::Topic do describe '#find_by_name_case_insensitive' do it 'returns topic with case insensitive name' do - %w(topic TOPIC Topic).each do |name| + %w[topic TOPIC Topic].each do |name| expect(described_class.find_by_name_case_insensitive(name)).to eq(topic) end end diff --git a/spec/models/prometheus_metric_spec.rb b/spec/models/prometheus_metric_spec.rb index a20f4edcf4a..c8a95aef8a6 100644 --- a/spec/models/prometheus_metric_spec.rb +++ b/spec/models/prometheus_metric_spec.rb @@ -94,16 +94,16 @@ RSpec.describe PrometheusMetric do describe '#required_metrics' do where(:group, :required_metrics) do - :nginx_ingress_vts | %w(nginx_upstream_responses_total nginx_upstream_response_msecs_avg) - :nginx_ingress | %w(nginx_ingress_controller_requests nginx_ingress_controller_ingress_upstream_latency_seconds_sum) - :ha_proxy | %w(haproxy_frontend_http_requests_total haproxy_frontend_http_responses_total) - :aws_elb | %w(aws_elb_request_count_sum aws_elb_latency_average aws_elb_httpcode_backend_5_xx_sum) - :nginx | %w(nginx_server_requests nginx_server_requestMsec) - :kubernetes | %w(container_memory_usage_bytes container_cpu_usage_seconds_total) - :business | %w() - :response | %w() - :system | %w() - :cluster_health | %w(container_memory_usage_bytes container_cpu_usage_seconds_total) + :nginx_ingress_vts | %w[nginx_upstream_responses_total nginx_upstream_response_msecs_avg] + :nginx_ingress | %w[nginx_ingress_controller_requests nginx_ingress_controller_ingress_upstream_latency_seconds_sum] + :ha_proxy | %w[haproxy_frontend_http_requests_total haproxy_frontend_http_responses_total] + :aws_elb | %w[aws_elb_request_count_sum aws_elb_latency_average aws_elb_httpcode_backend_5_xx_sum] + :nginx | %w[nginx_server_requests nginx_server_requestMsec] + :kubernetes | %w[container_memory_usage_bytes container_cpu_usage_seconds_total] + :business | %w[] + :response | %w[] + :system | %w[] + :cluster_health | %w[container_memory_usage_bytes container_cpu_usage_seconds_total] end with_them do diff --git a/spec/models/releases/link_spec.rb b/spec/models/releases/link_spec.rb index c4c9fba32d9..5d264af695b 100644 --- a/spec/models/releases/link_spec.rb +++ b/spec/models/releases/link_spec.rb @@ -82,7 +82,7 @@ RSpec.describe Releases::Link do describe 'supported protocols' do where(:protocol) do - %w(http https ftp) + %w[http https ftp] end with_them do diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 5c766035e98..f81a198a27d 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -743,7 +743,7 @@ RSpec.describe Repository, feature_category: :source_code_management do describe "#merged_branch_names", :clean_gitlab_redis_cache do subject { repository.merged_branch_names(branch_names) } - let(:branch_names) { %w(test beep boop definitely_merged) } + let(:branch_names) { %w[test beep boop definitely_merged] } let(:already_merged) { Set.new(["definitely_merged"]) } let(:write_hash) do @@ -1621,16 +1621,16 @@ RSpec.describe Repository, feature_category: :source_code_management do where(:branch_names, :tag_names, :result) do nil | nil | false - %w() | %w() | false - %w(a b) | %w() | false - %w() | %w(c d) | false - %w(a b) | %w(c d) | false - %w(a/b) | %w(c/d) | false - %w(a b) | %w(c d a/z) | true - %w(a b c/z) | %w(c d) | true - %w(a/b/z) | %w(a/b) | false # we only consider refs ambiguous before the first slash - %w(a/b/z) | %w(a/b a) | true - %w(ab) | %w(abc/d a b) | false + %w[] | %w[] | false + %w[a b] | %w[] | false + %w[] | %w[c d] | false + %w[a b] | %w[c d] | false + %w[a/b] | %w[c/d] | false + %w[a b] | %w[c d a/z] | true + %w[a b c/z] | %w[c d] | true + %w[a/b/z] | %w[a/b] | false # we only consider refs ambiguous before the first slash + %w[a/b/z] | %w[a/b a] | true + %w[ab] | %w[abc/d a b] | false end with_them do @@ -2596,7 +2596,7 @@ RSpec.describe Repository, feature_category: :source_code_management do describe '#expire_branches_cache' do it 'expires the cache' do expect(repository).to receive(:expire_method_caches) - .with(%i(branch_names merged_branch_names branch_count has_visible_content? has_ambiguous_refs?)) + .with(%i[branch_names merged_branch_names branch_count has_visible_content? has_ambiguous_refs?]) .and_call_original expect_next_instance_of(ProtectedBranches::CacheService) do |cache_service| @@ -2630,7 +2630,7 @@ RSpec.describe Repository, feature_category: :source_code_management do describe '#expire_tags_cache' do it 'expires the cache' do expect(repository).to receive(:expire_method_caches) - .with(%i(tag_names tag_count has_ambiguous_refs?)) + .with(%i[tag_names tag_count has_ambiguous_refs?]) .and_call_original repository.expire_tags_cache @@ -2889,7 +2889,7 @@ RSpec.describe Repository, feature_category: :source_code_management do describe '#expire_statistics_caches' do it 'expires the caches' do expect(repository).to receive(:expire_method_caches) - .with(%i(size recent_objects_size commit_count)) + .with(%i[size recent_objects_size commit_count]) repository.expire_statistics_caches end @@ -3090,13 +3090,13 @@ RSpec.describe Repository, feature_category: :source_code_management do describe '#refresh_method_caches' do it 'refreshes the caches of the given types' do expect(repository).to receive(:expire_method_caches) - .with(%i(readme_path license_blob license_gitaly)) + .with(%i[readme_path license_blob license_gitaly]) expect(repository).to receive(:readme_path) expect(repository).to receive(:license_blob) expect(repository).to receive(:license_gitaly) - repository.refresh_method_caches(%i(readme license)) + repository.refresh_method_caches(%i[readme license]) end end diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb index ec2dfb2634f..7eb1d9fda7b 100644 --- a/spec/models/snippet_spec.rb +++ b/spec/models/snippet_spec.rb @@ -614,7 +614,7 @@ RSpec.describe Snippet do context 'when file does not exist' do it 'removes nil values from the blobs array' do - allow(snippet).to receive(:list_files).and_return(%w(LICENSE non_existent_snippet_file)) + allow(snippet).to receive(:list_files).and_return(%w[LICENSE non_existent_snippet_file]) blobs = snippet.blobs expect(blobs.count).to eq 1 diff --git a/spec/models/terraform/state_spec.rb b/spec/models/terraform/state_spec.rb index fc0a6432149..df8051ebbc6 100644 --- a/spec/models/terraform/state_spec.rb +++ b/spec/models/terraform/state_spec.rb @@ -21,7 +21,7 @@ RSpec.describe Terraform::State, feature_category: :infrastructure_as_code do describe '.ordered_by_name' do let_it_be(:project) { create(:project) } - let(:names) { %w(state_d state_b state_a state_c) } + let(:names) { %w[state_d state_b state_a state_c] } subject { described_class.ordered_by_name } diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 09eb92e01e6..cff98cdb9fb 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -1280,7 +1280,7 @@ RSpec.describe User, feature_category: :user_profile do user = create(:user, username: 'CaMeLcAsEd') user2 = create(:user, username: 'UPPERCASE') - expect(described_class.by_username(%w(CAMELCASED uppercase))) + expect(described_class.by_username(%w[CAMELCASED uppercase])) .to contain_exactly(user, user2) end @@ -5833,37 +5833,37 @@ RSpec.describe User, feature_category: :user_profile do context 'oauth user' do it 'returns true if name can be synced' do - stub_omniauth_setting(sync_profile_attributes: %w(name location)) + stub_omniauth_setting(sync_profile_attributes: %w[name location]) expect(user.sync_attribute?(:name)).to be_truthy end it 'returns true if email can be synced' do - stub_omniauth_setting(sync_profile_attributes: %w(name email)) + stub_omniauth_setting(sync_profile_attributes: %w[name email]) expect(user.sync_attribute?(:email)).to be_truthy end it 'returns true if location can be synced' do - stub_omniauth_setting(sync_profile_attributes: %w(location email)) + stub_omniauth_setting(sync_profile_attributes: %w[location email]) expect(user.sync_attribute?(:email)).to be_truthy end it 'returns false if name can not be synced' do - stub_omniauth_setting(sync_profile_attributes: %w(location email)) + stub_omniauth_setting(sync_profile_attributes: %w[location email]) expect(user.sync_attribute?(:name)).to be_falsey end it 'returns false if email can not be synced' do - stub_omniauth_setting(sync_profile_attributes: %w(location name)) + stub_omniauth_setting(sync_profile_attributes: %w[location name]) expect(user.sync_attribute?(:email)).to be_falsey end it 'returns false if location can not be synced' do - stub_omniauth_setting(sync_profile_attributes: %w(name email)) + stub_omniauth_setting(sync_profile_attributes: %w[name email]) expect(user.sync_attribute?(:location)).to be_falsey end @@ -5894,7 +5894,7 @@ RSpec.describe User, feature_category: :user_profile do it 'returns true for email and location if ldap user and location declared as syncable' do allow(user).to receive(:ldap_user?).and_return(true) - stub_omniauth_setting(sync_profile_attributes: %w(location)) + stub_omniauth_setting(sync_profile_attributes: %w[location]) expect(user.sync_attribute?(:name)).to be_falsey expect(user.sync_attribute?(:email)).to be_truthy diff --git a/spec/models/web_ide_terminal_spec.rb b/spec/models/web_ide_terminal_spec.rb index fc30bc18f68..505b7531db4 100644 --- a/spec/models/web_ide_terminal_spec.rb +++ b/spec/models/web_ide_terminal_spec.rb @@ -45,7 +45,7 @@ RSpec.describe WebIdeTerminal do end it 'returns services aliases' do - expect(subject.services).to eq %w(postgres docker) + expect(subject.services).to eq %w[postgres docker] end end @@ -55,7 +55,7 @@ RSpec.describe WebIdeTerminal do end it 'returns all aliases' do - expect(subject.services).to eq %w(postgres docker ruby) + expect(subject.services).to eq %w[postgres docker ruby] end end @@ -71,7 +71,7 @@ RSpec.describe WebIdeTerminal do context 'when no image nor services' do let(:config) do - { script: %w(echo) } + { script: %w[echo] } end it 'returns an empty array' do diff --git a/spec/models/zoom_meeting_spec.rb b/spec/models/zoom_meeting_spec.rb index d3d75a19fed..b67a9d4a2ff 100644 --- a/spec/models/zoom_meeting_spec.rb +++ b/spec/models/zoom_meeting_spec.rb @@ -65,7 +65,7 @@ RSpec.describe ZoomMeeting do context 'with non-Zoom URL' do before do - subject.url = %{https://non-zoom.url} + subject.url = %(https://non-zoom.url) end include_examples 'invalid Zoom URL' @@ -73,7 +73,7 @@ RSpec.describe ZoomMeeting do context 'with multiple Zoom-URLs' do before do - subject.url = %{https://zoom.us/j/123 https://zoom.us/j/456} + subject.url = %(https://zoom.us/j/123 https://zoom.us/j/456) end include_examples 'invalid Zoom URL' diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb index d0e4327a248..5e79569e0c4 100644 --- a/spec/policies/project_policy_spec.rb +++ b/spec/policies/project_policy_spec.rb @@ -391,7 +391,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do end let(:maintainer_abilities) do - %w(create_build create_pipeline) + %w[create_build create_pipeline] end it 'does not allow pushing code' do @@ -413,7 +413,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do end context 'importing members from another project' do - %w(maintainer owner).each do |role| + %w[maintainer owner].each do |role| context "with #{role}" do let(:current_user) { send(role) } @@ -421,7 +421,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do end end - %w(guest reporter developer anonymous).each do |role| + %w[guest reporter developer anonymous].each do |role| context "with #{role}" do let(:current_user) { send(role) } @@ -443,7 +443,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do end context 'importing work items' do - %w(reporter developer maintainer owner).each do |role| + %w[reporter developer maintainer owner].each do |role| context "with #{role}" do let(:current_user) { send(role) } @@ -451,7 +451,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do end end - %w(guest anonymous).each do |role| + %w[guest anonymous].each do |role| context "with #{role}" do let(:current_user) { send(role) } @@ -473,7 +473,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do end context 'reading usage quotas' do - %w(maintainer owner).each do |role| + %w[maintainer owner].each do |role| context "with #{role}" do let(:current_user) { send(role) } @@ -481,7 +481,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do end end - %w(guest reporter developer anonymous).each do |role| + %w[guest reporter developer anonymous].each do |role| context "with #{role}" do let(:current_user) { send(role) } @@ -692,7 +692,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do it { is_expected.to be_disallowed(:fork_project) } end - %w(reporter developer maintainer).each do |role| + %w[reporter developer maintainer].each do |role| context role do let(:current_user) { send(role) } @@ -791,7 +791,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do end end - %w(guest reporter developer maintainer owner).each do |role| + %w[guest reporter developer maintainer owner].each do |role| context role do let(:current_user) { send(role) } @@ -819,7 +819,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do end end - %w(guest reporter developer maintainer owner).each do |role| + %w[guest reporter developer maintainer owner].each do |role| context role do let(:current_user) { send(role) } @@ -1439,7 +1439,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do end context 'security configuration feature' do - %w(guest reporter).each do |role| + %w[guest reporter].each do |role| context role do let(:current_user) { send(role) } @@ -1449,7 +1449,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do end end - %w(developer maintainer owner).each do |role| + %w[developer maintainer owner].each do |role| context role do let(:current_user) { send(role) } @@ -1461,7 +1461,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do end context 'infrastructure google cloud feature' do - %w(guest reporter developer).each do |role| + %w[guest reporter developer].each do |role| context role do let(:current_user) { send(role) } @@ -1471,7 +1471,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do end end - %w(maintainer owner).each do |role| + %w[maintainer owner].each do |role| context role do let(:current_user) { send(role) } @@ -1483,7 +1483,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do end context 'infrastructure aws feature' do - %w(guest reporter developer).each do |role| + %w[guest reporter developer].each do |role| context role do let(:current_user) { send(role) } @@ -1493,7 +1493,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do end end - %w(maintainer owner).each do |role| + %w[maintainer owner].each do |role| context role do let(:current_user) { send(role) } @@ -1974,7 +1974,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do context 'project member' do let(:project) { private_project } - %w(guest reporter developer maintainer).each do |role| + %w[guest reporter developer maintainer].each do |role| context role do let(:current_user) { send(role) } @@ -2003,7 +2003,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do end context 'project member' do - %w(guest reporter developer maintainer).each do |role| + %w[guest reporter developer maintainer].each do |role| context role do before do project.add_member(current_user, role.to_sym) @@ -2037,7 +2037,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do end context 'project member' do - %w(guest reporter developer maintainer).each do |role| + %w[guest reporter developer maintainer].each do |role| context role do before do project.add_member(current_user, role.to_sym) @@ -2067,7 +2067,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do let(:current_user) { create(:user) } context 'project member' do - %w(guest reporter developer maintainer).each do |role| + %w[guest reporter developer maintainer].each do |role| context role do before do project.add_member(current_user, role.to_sym) @@ -2827,7 +2827,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do end end - %w(guest reporter developer).each do |role| + %w[guest reporter developer].each do |role| context role do let(:current_user) { send(role) } @@ -2835,7 +2835,7 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do end end - %w(maintainer owner).each do |role| + %w[maintainer owner].each do |role| context role do let(:current_user) { send(role) } diff --git a/spec/presenters/ci/pipeline_artifacts/code_coverage_presenter_spec.rb b/spec/presenters/ci/pipeline_artifacts/code_coverage_presenter_spec.rb index e679f5fa144..2973040dd6a 100644 --- a/spec/presenters/ci/pipeline_artifacts/code_coverage_presenter_spec.rb +++ b/spec/presenters/ci/pipeline_artifacts/code_coverage_presenter_spec.rb @@ -12,7 +12,7 @@ RSpec.describe Ci::PipelineArtifacts::CodeCoveragePresenter do context 'when code coverage has data' do context 'when filenames is empty' do - let(:filenames) { %w() } + let(:filenames) { %w[] } it 'returns hash without coverage' do expect(subject).to match(files: {}) @@ -20,7 +20,7 @@ RSpec.describe Ci::PipelineArtifacts::CodeCoveragePresenter do end context 'when filenames do not match code coverage data' do - let(:filenames) { %w(demo.rb) } + let(:filenames) { %w[demo.rb] } it 'returns hash without coverage' do expect(subject).to match(files: {}) @@ -29,7 +29,7 @@ RSpec.describe Ci::PipelineArtifacts::CodeCoveragePresenter do context 'when filenames matches code coverage data' do context 'when asking for one filename' do - let(:filenames) { %w(file_a.rb) } + let(:filenames) { %w[file_a.rb] } it 'returns coverage for the given filename' do expect(subject).to match(files: { "file_a.rb" => { "1" => 1, "2" => 1, "3" => 1 } }) @@ -37,7 +37,7 @@ RSpec.describe Ci::PipelineArtifacts::CodeCoveragePresenter do end context 'when asking for multiple filenames' do - let(:filenames) { %w(file_a.rb file_b.rb) } + let(:filenames) { %w[file_a.rb file_b.rb] } it 'returns coverage for a the given filenames' do expect(subject).to match( diff --git a/spec/presenters/ci/pipeline_artifacts/code_quality_mr_diff_presenter_spec.rb b/spec/presenters/ci/pipeline_artifacts/code_quality_mr_diff_presenter_spec.rb index 99c82795210..f4f0990240d 100644 --- a/spec/presenters/ci/pipeline_artifacts/code_quality_mr_diff_presenter_spec.rb +++ b/spec/presenters/ci/pipeline_artifacts/code_quality_mr_diff_presenter_spec.rb @@ -13,7 +13,7 @@ RSpec.describe Ci::PipelineArtifacts::CodeQualityMrDiffPresenter, feature_catego context 'when code quality has data' do context 'when filenames is empty' do - let(:filenames) { %w() } + let(:filenames) { %w[] } it 'returns hash without quality' do expect(quality_data).to match(files: {}) @@ -21,7 +21,7 @@ RSpec.describe Ci::PipelineArtifacts::CodeQualityMrDiffPresenter, feature_catego end context 'when filenames do not match code quality data' do - let(:filenames) { %w(demo.rb) } + let(:filenames) { %w[demo.rb] } it 'returns hash without quality' do expect(quality_data).to match(files: {}) @@ -30,7 +30,7 @@ RSpec.describe Ci::PipelineArtifacts::CodeQualityMrDiffPresenter, feature_catego context 'when filenames matches code quality data' do context 'when asking for one filename' do - let(:filenames) { %w(file_a.rb) } + let(:filenames) { %w[file_a.rb] } it 'returns quality for the given filename' do expect(quality_data).to match( @@ -45,7 +45,7 @@ RSpec.describe Ci::PipelineArtifacts::CodeQualityMrDiffPresenter, feature_catego end context 'when asking for multiple filenames' do - let(:filenames) { %w(file_a.rb file_b.rb) } + let(:filenames) { %w[file_a.rb file_b.rb] } it 'returns quality for the given filenames' do expect(quality_data).to match( diff --git a/spec/presenters/packages/nuget/packages_metadata_presenter_spec.rb b/spec/presenters/packages/nuget/packages_metadata_presenter_spec.rb index 38b33a0ec4b..c7bdff9dd61 100644 --- a/spec/presenters/packages/nuget/packages_metadata_presenter_spec.rb +++ b/spec/presenters/packages/nuget/packages_metadata_presenter_spec.rb @@ -17,7 +17,7 @@ RSpec.describe Packages::Nuget::PackagesMetadataPresenter, feature_category: :pa end describe '#items' do - let(:tag_names) { %w(tag1 tag2) } + let(:tag_names) { %w[tag1 tag2] } subject { presenter.items } diff --git a/spec/presenters/packages/nuget/search_results_presenter_spec.rb b/spec/presenters/packages/nuget/search_results_presenter_spec.rb index e761a8740ef..7501cb75682 100644 --- a/spec/presenters/packages/nuget/search_results_presenter_spec.rb +++ b/spec/presenters/packages/nuget/search_results_presenter_spec.rb @@ -25,7 +25,7 @@ RSpec.describe Packages::Nuget::SearchResultsPresenter, feature_category: :packa it 'returns the proper data structure' do expect(data.size).to eq 3 pkg_a, pkg_b, pkg_c = data - expect_package_result(pkg_a, package_a.name, [package_a.version], %w(tag1 tag2), with_metadatum: true) + expect_package_result(pkg_a, package_a.name, [package_a.version], %w[tag1 tag2], with_metadatum: true) expect_package_result(pkg_b, packages_b.first.name, packages_b.map(&:version)) expect_package_result(pkg_c, packages_c.first.name, packages_c.map(&:version)) end diff --git a/spec/requests/api/graphql/mutations/issues/set_due_date_spec.rb b/spec/requests/api/graphql/mutations/issues/set_due_date_spec.rb index 1a5a64e4196..ec71e44464a 100644 --- a/spec/requests/api/graphql/mutations/issues/set_due_date_spec.rb +++ b/spec/requests/api/graphql/mutations/issues/set_due_date_spec.rb @@ -68,7 +68,7 @@ RSpec.describe 'Setting Due Date of an issue', feature_category: :team_planning it 'returns an error' do post_graphql_mutation(mutation, current_user: current_user) - expect(graphql_errors).to include(a_hash_including('message' => /Arguments must be provided: dueDate/)) + expect(graphql_errors).to include(a_hash_including('message' => 'issueSetDueDate has the wrong arguments')) end end diff --git a/spec/requests/api/graphql/mutations/merge_requests/update_spec.rb b/spec/requests/api/graphql/mutations/merge_requests/update_spec.rb index 48db23569b6..3e2bdb376ad 100644 --- a/spec/requests/api/graphql/mutations/merge_requests/update_spec.rb +++ b/spec/requests/api/graphql/mutations/merge_requests/update_spec.rb @@ -28,5 +28,17 @@ RSpec.describe 'Update of an existing merge request', feature_category: :code_re let(:resource) { merge_request } let(:mutation_name) { 'mergeRequestUpdate' } end + + context 'when required arguments are missing' do + let(:input_params) { {} } + + it_behaves_like 'a mutation that returns top-level errors' do + let(:match_errors) do + include(end_with( + 'invalid value for projectPath (Expected value to not be null), iid (Expected value to not be null)' + )) + end + end + end end end diff --git a/spec/requests/api/helm_packages_spec.rb b/spec/requests/api/helm_packages_spec.rb index d6afd6f86ff..75f60c59759 100644 --- a/spec/requests/api/helm_packages_spec.rb +++ b/spec/requests/api/helm_packages_spec.rb @@ -101,6 +101,12 @@ RSpec.describe API::HelmPackages, feature_category: :package_registry do end it_behaves_like 'deploy token for package GET requests' + + context 'when format param is not nil' do + let(:url) { "/projects/#{project.id}/packages/helm/stable/charts/#{package.name}-#{package.version}.tgz.prov" } + + it_behaves_like 'rejects helm packages access', :maintainer, :not_found, '{"message":"404 Format prov Not Found"}' + end end describe 'POST /api/v4/projects/:id/packages/helm/api/:channel/charts/authorize' do diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index c6e1605010e..ce90b9f1474 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -2783,10 +2783,20 @@ RSpec.describe API::Projects, :aggregate_failures, feature_category: :groups_and expect(json_response['shared_with_groups'][0]['expires_at']).to eq(expires_at.to_s) end - it 'returns a project by path name' do - get api(path, user) - expect(response).to have_gitlab_http_status(:ok) - expect(json_response['name']).to eq(project.name) + context 'when path name is specified' do + it 'returns a project' do + get api("/projects/#{CGI.escape(project.full_path)}", user) + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response['name']).to eq(project.name) + end + + it 'returns a project using case-insensitive search' do + get api("/projects/#{CGI.escape(project.full_path.swapcase)}", user) + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response['name']).to eq(project.name) + end end context 'when a project is moved' do diff --git a/spec/services/ci/play_build_service_spec.rb b/spec/services/ci/play_build_service_spec.rb index 46b6622d6ec..c5651dc4502 100644 --- a/spec/services/ci/play_build_service_spec.rb +++ b/spec/services/ci/play_build_service_spec.rb @@ -63,10 +63,6 @@ RSpec.describe Ci::PlayBuildService, '#execute', feature_category: :continuous_i context 'when a subsequent job is skipped' do let!(:job) { create(:ci_build, :skipped, pipeline: pipeline, stage_idx: build.stage_idx + 1) } - before do - create(:ci_build_need, build: job, name: build.name) - end - it 'marks the subsequent job as processable' do expect { service.execute(build) }.to change { job.reload.status }.from('skipped').to('created') end diff --git a/spec/services/git/branch_hooks_service_spec.rb b/spec/services/git/branch_hooks_service_spec.rb index 3050d6c5eca..8fd542542ae 100644 --- a/spec/services/git/branch_hooks_service_spec.rb +++ b/spec/services/git/branch_hooks_service_spec.rb @@ -133,27 +133,14 @@ RSpec.describe Git::BranchHooksService, :clean_gitlab_redis_shared_state, featur expect(Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: 'o_pipeline_authoring_unique_users_committing_ciconfigfile', start_date: time, end_date: time + 7.days)).to eq(1) end - context 'when usage ping is disabled' do - before do - allow(::ServicePing::ServicePingSettings).to receive(:enabled?).and_return(false) - end - - it 'does not track the event' do - execute_service - - expect(Gitlab::UsageDataCounters::HLLRedisCounter) - .not_to receive(:track_event).with(*tracking_params) - end - end - context 'when the branch is not the main branch' do let(:branch) { 'feature' } it 'does not track the event' do - execute_service - expect(Gitlab::UsageDataCounters::HLLRedisCounter) .not_to receive(:track_event).with(*tracking_params) + + execute_service end end @@ -163,10 +150,10 @@ RSpec.describe Git::BranchHooksService, :clean_gitlab_redis_shared_state, featur end it 'does not track the event' do - execute_service - expect(Gitlab::UsageDataCounters::HLLRedisCounter) .not_to receive(:track_event).with(*tracking_params) + + execute_service end end end diff --git a/spec/support/helpers/packages_manager_api_spec_helper.rb b/spec/support/helpers/packages_manager_api_spec_helper.rb deleted file mode 100644 index 1c9fce183e9..00000000000 --- a/spec/support/helpers/packages_manager_api_spec_helper.rb +++ /dev/null @@ -1,34 +0,0 @@ -# frozen_string_literal: true - -module PackagesManagerApiSpecHelpers - def build_jwt(personal_access_token, secret: jwt_secret, user_id: nil) - JSONWebToken::HMACToken.new(secret).tap do |jwt| - jwt['access_token'] = personal_access_token.token - jwt['user_id'] = user_id || personal_access_token.user_id - end - end - - def build_jwt_from_job(job, secret: jwt_secret) - JSONWebToken::HMACToken.new(secret).tap do |jwt| - jwt['access_token'] = job.token - jwt['user_id'] = job.user.id - end - end - - def build_jwt_from_deploy_token(deploy_token, secret: jwt_secret) - JSONWebToken::HMACToken.new(secret).tap do |jwt| - jwt['access_token'] = deploy_token.token - jwt['user_id'] = deploy_token.username - end - end - - def temp_file(package_tmp) - upload_path = ::Packages::PackageFileUploader.workhorse_local_upload_path - file_path = "#{upload_path}/#{package_tmp}" - - FileUtils.mkdir_p(upload_path) - File.write(file_path, 'test') - - UploadedFile.new(file_path, filename: File.basename(file_path)) - end -end diff --git a/spec/support/helpers/packages_manager_api_spec_helpers.rb b/spec/support/helpers/packages_manager_api_spec_helpers.rb new file mode 100644 index 00000000000..1c9fce183e9 --- /dev/null +++ b/spec/support/helpers/packages_manager_api_spec_helpers.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +module PackagesManagerApiSpecHelpers + def build_jwt(personal_access_token, secret: jwt_secret, user_id: nil) + JSONWebToken::HMACToken.new(secret).tap do |jwt| + jwt['access_token'] = personal_access_token.token + jwt['user_id'] = user_id || personal_access_token.user_id + end + end + + def build_jwt_from_job(job, secret: jwt_secret) + JSONWebToken::HMACToken.new(secret).tap do |jwt| + jwt['access_token'] = job.token + jwt['user_id'] = job.user.id + end + end + + def build_jwt_from_deploy_token(deploy_token, secret: jwt_secret) + JSONWebToken::HMACToken.new(secret).tap do |jwt| + jwt['access_token'] = deploy_token.token + jwt['user_id'] = deploy_token.username + end + end + + def temp_file(package_tmp) + upload_path = ::Packages::PackageFileUploader.workhorse_local_upload_path + file_path = "#{upload_path}/#{package_tmp}" + + FileUtils.mkdir_p(upload_path) + File.write(file_path, 'test') + + UploadedFile.new(file_path, filename: File.basename(file_path)) + end +end diff --git a/spec/support/rspec_order_todo.yml b/spec/support/rspec_order_todo.yml index 93370935125..5a70d1f1d5e 100644 --- a/spec/support/rspec_order_todo.yml +++ b/spec/support/rspec_order_todo.yml @@ -4329,7 +4329,6 @@ - './spec/graphql/mutations/alert_management/prometheus_integration/reset_token_spec.rb' - './spec/graphql/mutations/alert_management/prometheus_integration/update_spec.rb' - './spec/graphql/mutations/alert_management/update_alert_status_spec.rb' -- './spec/graphql/mutations/base_mutation_spec.rb' - './spec/graphql/mutations/boards/issues/issue_move_list_spec.rb' - './spec/graphql/mutations/boards/lists/create_spec.rb' - './spec/graphql/mutations/boards/lists/update_spec.rb' diff --git a/spec/support/shared_examples/requests/api/helm_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/helm_packages_shared_examples.rb index 7803f0ff04d..9c20b95eb80 100644 --- a/spec/support/shared_examples/requests/api/helm_packages_shared_examples.rb +++ b/spec/support/shared_examples/requests/api/helm_packages_shared_examples.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -RSpec.shared_examples 'rejects helm packages access' do |user_type, status| +RSpec.shared_examples 'rejects helm packages access' do |user_type, status, body| context "for user type #{user_type}" do before do project.send("add_#{user_type}", user) if user_type != :anonymous && user_type != :not_a_member @@ -15,6 +15,14 @@ RSpec.shared_examples 'rejects helm packages access' do |user_type, status| expect(response.headers['WWW-Authenticate']).to eq 'Basic realm="GitLab Packages Registry"' end end + + if body + it 'has the correct body' do + subject + + expect(response.body).to eq(body) + end + end end end diff --git a/workhorse/internal/goredis/goredis.go b/workhorse/internal/goredis/goredis.go index 13a9d4cc34f..5566e5a3434 100644 --- a/workhorse/internal/goredis/goredis.go +++ b/workhorse/internal/goredis/goredis.go @@ -150,17 +150,12 @@ func configureRedis(cfg *config.RedisConfig) (*redis.Client, error) { } func configureSentinel(cfg *config.RedisConfig) *redis.Client { - sentinels := make([]string, len(cfg.Sentinel)) - for i := range cfg.Sentinel { - sentinelDetails := cfg.Sentinel[i] - sentinels[i] = fmt.Sprintf("%s:%s", sentinelDetails.Hostname(), sentinelDetails.Port()) - } - + sentinelPassword, sentinels := sentinelOptions(cfg) client := redis.NewFailoverClient(&redis.FailoverOptions{ MasterName: cfg.SentinelMaster, SentinelAddrs: sentinels, Password: cfg.Password, - SentinelPassword: cfg.SentinelPassword, + SentinelPassword: sentinelPassword, DB: getOrDefault(cfg.DB, 0), PoolSize: getOrDefault(cfg.MaxActive, defaultMaxActive), @@ -178,6 +173,25 @@ func configureSentinel(cfg *config.RedisConfig) *redis.Client { return client } +// sentinelOptions extracts the sentinel password and addresses in : format +// the order of priority for the passwords is: SentinelPassword -> first password-in-url +func sentinelOptions(cfg *config.RedisConfig) (string, []string) { + sentinels := make([]string, len(cfg.Sentinel)) + sentinelPassword := cfg.SentinelPassword + + for i := range cfg.Sentinel { + sentinelDetails := cfg.Sentinel[i] + sentinels[i] = fmt.Sprintf("%s:%s", sentinelDetails.Hostname(), sentinelDetails.Port()) + + if pw, exist := sentinelDetails.User.Password(); exist && len(sentinelPassword) == 0 { + // sets password using the first non-empty password + sentinelPassword = pw + } + } + + return sentinelPassword, sentinels +} + func getOrDefault(ptr *int, val int) int { if ptr != nil { return *ptr diff --git a/workhorse/internal/goredis/goredis_test.go b/workhorse/internal/goredis/goredis_test.go index 6b281229ea4..735b2076b0c 100644 --- a/workhorse/internal/goredis/goredis_test.go +++ b/workhorse/internal/goredis/goredis_test.go @@ -105,3 +105,58 @@ func TestConnectToSentinel(t *testing.T) { }) } } + +func TestSentinelOptions(t *testing.T) { + testCases := []struct { + description string + inputSentinelPassword string + inputSentinel []string + password string + sentinels []string + }{ + { + description: "no sentinel passwords", + inputSentinel: []string{"tcp://localhost:26480"}, + sentinels: []string{"localhost:26480"}, + }, + { + description: "specific sentinel password defined", + inputSentinel: []string{"tcp://localhost:26480"}, + inputSentinelPassword: "password1", + sentinels: []string{"localhost:26480"}, + password: "password1", + }, + { + description: "specific sentinel password defined in url", + inputSentinel: []string{"tcp://:password2@localhost:26480", "tcp://:password3@localhost:26481"}, + sentinels: []string{"localhost:26480", "localhost:26481"}, + password: "password2", + }, + { + description: "passwords defined specifically and in url", + inputSentinel: []string{"tcp://:password2@localhost:26480", "tcp://:password3@localhost:26481"}, + sentinels: []string{"localhost:26480", "localhost:26481"}, + inputSentinelPassword: "password1", + password: "password1", + }, + } + + for _, tc := range testCases { + t.Run(tc.description, func(t *testing.T) { + sentinelUrls := make([]config.TomlURL, len(tc.inputSentinel)) + + for i, str := range tc.inputSentinel { + parsedURL := helper.URLMustParse(str) + sentinelUrls[i] = config.TomlURL{URL: *parsedURL} + } + + outputPw, outputSentinels := sentinelOptions(&config.RedisConfig{ + Sentinel: sentinelUrls, + SentinelPassword: tc.inputSentinelPassword, + }) + + require.Equal(t, tc.password, outputPw) + require.Equal(t, tc.sentinels, outputSentinels) + }) + } +} -- cgit v1.2.3