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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-10-31 15:11:01 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-10-31 15:11:01 +0300
commitf52f8542b47c9e00ddf420abaf2263de168988f9 (patch)
tree568225882da5cc4deb746d2d4fc362c6076fb708
parent6a5ef9b75d38f39cd2a6a2392fadfbd3b966b884 (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.rubocop_todo/rspec/feature_category.yml1
-rw-r--r--.rubocop_todo/style/percent_literal_delimiters.yml60
-rw-r--r--app/assets/javascripts/blob/filepath_form/components/template_selector.vue5
-rw-r--r--app/assets/javascripts/editor/constants.js5
-rw-r--r--app/assets/javascripts/header.js3
-rw-r--r--app/assets/javascripts/ide/components/repo_editor.vue9
-rw-r--r--app/assets/javascripts/ide/lib/alerts/index.js3
-rw-r--r--app/assets/javascripts/ide/stores/modules/file_templates/getters.js3
-rw-r--r--app/assets/javascripts/issues/issue.js2
-rw-r--r--app/assets/javascripts/lib/utils/common_utils.js15
-rw-r--r--app/assets/javascripts/lib/utils/constants.js3
-rw-r--r--app/assets/javascripts/pipeline_wizard/pipeline_wizard.vue3
-rw-r--r--app/assets/javascripts/vue_shared/components/list_selector/constants.js7
-rw-r--r--app/assets/javascripts/vue_shared/components/list_selector/index.vue135
-rw-r--r--app/assets/javascripts/vue_shared/components/list_selector/user.vue55
-rw-r--r--app/graphql/mutations/base_mutation.rb6
-rw-r--r--app/graphql/types/base_argument.rb22
-rw-r--r--app/graphql/types/permission_types/base_permission_type.rb2
-rw-r--r--app/services/git/branch_hooks_service.rb1
-rw-r--r--db/post_migrate/20231030095419_remove_temp_index_to_packages_on_project_id_when_npm_and_not_pending_destruction.rb23
-rw-r--r--db/schema_migrations/202310300954191
-rw-r--r--db/structure.sql2
-rw-r--r--doc/api/graphql/reference/index.md268
-rw-r--r--doc/api/scim.md2
-rw-r--r--doc/development/internal_api/index.md4
-rw-r--r--lib/api/helm_packages.rb2
-rw-r--r--lib/api/helpers.rb2
-rw-r--r--lib/gitlab/ci/yaml_processor/dag.rb2
-rw-r--r--lib/gitlab/internal_events.rb2
-rw-r--r--lib/gitlab/usage_data_counters/hll_redis_counter.rb2
-rw-r--r--lib/gitlab/usage_data_counters/redis_counter.rb4
-rw-r--r--locale/gitlab.pot12
-rw-r--r--qa/Gemfile2
-rw-r--r--qa/Gemfile.lock6
-rw-r--r--spec/frontend/fixtures/issues.rb2
-rw-r--r--spec/frontend/fixtures/snippet.rb2
-rw-r--r--spec/frontend/header_spec.js9
-rw-r--r--spec/frontend/ide/components/repo_editor_spec.js9
-rw-r--r--spec/frontend/issues/issue_spec.js12
-rw-r--r--spec/frontend/lib/utils/common_utils_spec.js24
-rw-r--r--spec/frontend/shortcuts_spec.js40
-rw-r--r--spec/frontend/vue_shared/components/list_selector/index_spec.js134
-rw-r--r--spec/frontend/vue_shared/components/list_selector/mock_data.js25
-rw-r--r--spec/frontend/vue_shared/components/list_selector/user_spec.js55
-rw-r--r--spec/graphql/mutations/base_mutation_spec.rb58
-rw-r--r--spec/graphql/mutations/ci/runner/delete_spec.rb2
-rw-r--r--spec/graphql/mutations/ci/runner/update_spec.rb2
-rw-r--r--spec/graphql/mutations/merge_requests/update_spec.rb14
-rw-r--r--spec/graphql/types/base_argument_spec.rb39
-rw-r--r--spec/lib/gitlab/ci/yaml_processor/dag_spec.rb12
-rw-r--r--spec/lib/gitlab/ci/yaml_processor_spec.rb17
-rw-r--r--spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb88
-rw-r--r--spec/lib/gitlab/usage_data_counters/redis_counter_spec.rb48
-rw-r--r--spec/metrics_server/metrics_server_spec.rb4
-rw-r--r--spec/models/alert_management/http_integration_spec.rb6
-rw-r--r--spec/models/appearance_spec.rb2
-rw-r--r--spec/models/application_setting_spec.rb8
-rw-r--r--spec/models/authentication_event_spec.rb4
-rw-r--r--spec/models/blob_viewer/base_spec.rb4
-rw-r--r--spec/models/ci/build_dependencies_spec.rb6
-rw-r--r--spec/models/ci/build_spec.rb38
-rw-r--r--spec/models/ci/job_artifact_spec.rb2
-rw-r--r--spec/models/ci/pipeline_spec.rb4
-rw-r--r--spec/models/ci/runner_spec.rb2
-rw-r--r--spec/models/clusters/agent_spec.rb2
-rw-r--r--spec/models/clusters/platforms/kubernetes_spec.rb2
-rw-r--r--spec/models/commit_range_spec.rb2
-rw-r--r--spec/models/commit_spec.rb4
-rw-r--r--spec/models/commit_status_spec.rb2
-rw-r--r--spec/models/compare_spec.rb4
-rw-r--r--spec/models/concerns/awardable_spec.rb8
-rw-r--r--spec/models/concerns/case_sensitivity_spec.rb6
-rw-r--r--spec/models/concerns/featurable_spec.rb2
-rw-r--r--spec/models/concerns/ignorable_columns_spec.rb4
-rw-r--r--spec/models/concerns/issuable_spec.rb4
-rw-r--r--spec/models/concerns/pg_full_text_searchable_spec.rb4
-rw-r--r--spec/models/concerns/project_features_compatibility_spec.rb6
-rw-r--r--spec/models/concerns/reactive_caching_spec.rb4
-rw-r--r--spec/models/concerns/sortable_spec.rb22
-rw-r--r--spec/models/deployment_spec.rb10
-rw-r--r--spec/models/diff_viewer/base_spec.rb4
-rw-r--r--spec/models/environment_spec.rb10
-rw-r--r--spec/models/group_label_spec.rb2
-rw-r--r--spec/models/instance_configuration_spec.rb4
-rw-r--r--spec/models/integration_spec.rb2
-rw-r--r--spec/models/integrations/buildkite_spec.rb2
-rw-r--r--spec/models/integrations/campfire_spec.rb2
-rw-r--r--spec/models/integrations/jira_spec.rb12
-rw-r--r--spec/models/integrations/teamcity_spec.rb4
-rw-r--r--spec/models/issue_spec.rb8
-rw-r--r--spec/models/merge_request_diff_spec.rb2
-rw-r--r--spec/models/namespace_statistics_spec.rb2
-rw-r--r--spec/models/packages/package_spec.rb2
-rw-r--r--spec/models/packages/tag_spec.rb2
-rw-r--r--spec/models/pages_domain_spec.rb18
-rw-r--r--spec/models/personal_access_token_spec.rb2
-rw-r--r--spec/models/project_feature_spec.rb4
-rw-r--r--spec/models/project_label_spec.rb2
-rw-r--r--spec/models/project_spec.rb14
-rw-r--r--spec/models/projects/topic_spec.rb2
-rw-r--r--spec/models/prometheus_metric_spec.rb20
-rw-r--r--spec/models/releases/link_spec.rb2
-rw-r--r--spec/models/repository_spec.rb32
-rw-r--r--spec/models/snippet_spec.rb2
-rw-r--r--spec/models/terraform/state_spec.rb2
-rw-r--r--spec/models/user_spec.rb16
-rw-r--r--spec/models/web_ide_terminal_spec.rb6
-rw-r--r--spec/models/zoom_meeting_spec.rb4
-rw-r--r--spec/policies/project_policy_spec.rb44
-rw-r--r--spec/presenters/ci/pipeline_artifacts/code_coverage_presenter_spec.rb8
-rw-r--r--spec/presenters/ci/pipeline_artifacts/code_quality_mr_diff_presenter_spec.rb8
-rw-r--r--spec/presenters/packages/nuget/packages_metadata_presenter_spec.rb2
-rw-r--r--spec/presenters/packages/nuget/search_results_presenter_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/issues/set_due_date_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/merge_requests/update_spec.rb12
-rw-r--r--spec/requests/api/helm_packages_spec.rb6
-rw-r--r--spec/requests/api/projects_spec.rb18
-rw-r--r--spec/services/ci/play_build_service_spec.rb4
-rw-r--r--spec/services/git/branch_hooks_service_spec.rb21
-rw-r--r--spec/support/helpers/packages_manager_api_spec_helpers.rb (renamed from spec/support/helpers/packages_manager_api_spec_helper.rb)0
-rw-r--r--spec/support/rspec_order_todo.yml1
-rw-r--r--spec/support/shared_examples/requests/api/helm_packages_shared_examples.rb10
-rw-r--r--workhorse/internal/goredis/goredis.go28
-rw-r--r--workhorse/internal/goredis/goredis_test.go55
124 files changed, 1110 insertions, 727 deletions
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 @@
<script>
import { parseDocument } from 'yaml';
+import { DEFAULT_CI_CONFIG_PATH } from '~/lib/utils/constants';
import WizardWrapper from './components/wrapper.vue';
export default {
@@ -23,7 +24,7 @@ export default {
defaultFilename: {
type: String,
required: false,
- default: '.gitlab-ci.yml',
+ default: DEFAULT_CI_CONFIG_PATH,
},
},
computed: {
diff --git a/app/assets/javascripts/vue_shared/components/list_selector/constants.js b/app/assets/javascripts/vue_shared/components/list_selector/constants.js
new file mode 100644
index 00000000000..c9db79581d1
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/list_selector/constants.js
@@ -0,0 +1,7 @@
+import { __ } from '~/locale';
+
+// Note, we can extend this config in future to make the component work in other contexts
+// https://gitlab.com/gitlab-org/gitlab/-/issues/428865
+export const CONFIG = {
+ users: { title: __('Users'), icon: 'user', filterKey: 'username' },
+};
diff --git a/app/assets/javascripts/vue_shared/components/list_selector/index.vue b/app/assets/javascripts/vue_shared/components/list_selector/index.vue
new file mode 100644
index 00000000000..237369f5900
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/list_selector/index.vue
@@ -0,0 +1,135 @@
+<script>
+import { GlCard, GlIcon, GlCollapsibleListbox, GlSearchBoxByType } from '@gitlab/ui';
+import usersAutocompleteQuery from '~/graphql_shared/queries/users_autocomplete.query.graphql';
+import User from './user.vue';
+import { CONFIG } from './constants';
+
+export default {
+ name: 'ListSelector',
+ components: {
+ GlCard,
+ GlIcon,
+ GlSearchBoxByType,
+ GlCollapsibleListbox,
+ User,
+ },
+ props: {
+ title: {
+ type: String,
+ required: true,
+ },
+ type: {
+ type: String,
+ required: true,
+ },
+ selectedItems: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ projectPath: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ },
+ data() {
+ return {
+ searchValue: '',
+ isProject: true, // TODO: implement a way to distinguish between project/group
+ selected: [],
+ items: [],
+ };
+ },
+ computed: {
+ config() {
+ return CONFIG[this.type];
+ },
+ searchItems() {
+ return (
+ this.items?.map((item) => ({
+ value: item.username,
+ text: item.name,
+ ...item,
+ })) || []
+ );
+ },
+ component() {
+ // Note, we can extend this for the component to support other contexts
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/428865
+ return User;
+ },
+ },
+ methods: {
+ async handleSearchInput(search) {
+ this.$refs.results.open();
+ this.items = await this.fetchUsersBySearchTerm(search);
+ },
+ fetchUsersBySearchTerm(search) {
+ const namespace = this.isProject ? 'project' : 'group';
+ return this.$apollo
+ .query({
+ query: usersAutocompleteQuery,
+ variables: { fullPath: this.projectPath, search, isProject: this.isProject },
+ })
+ .then(({ data }) => data[namespace]?.autocompleteUsers);
+ },
+ getItemByKey(key) {
+ return this.searchItems.find((item) => item[this.config.filterKey] === key);
+ },
+ handleSelectItem(key) {
+ this.$emit('select', this.getItemByKey(key));
+ },
+ handleDeleteItem(key) {
+ this.$emit('delete', key);
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-card header-class="gl-new-card-header gl-border-none" body-class="gl-card-footer">
+ <template #header
+ ><strong
+ >{{ title }}
+ <span class="gl-text-gray-500"
+ ><gl-icon :name="config.icon" /> {{ selectedItems.length }}</span
+ ></strong
+ ></template
+ >
+
+ <gl-collapsible-listbox
+ ref="results"
+ v-model="selected"
+ class="list-selector gl-mb-4 gl-display-block"
+ :items="searchItems"
+ multiple
+ @shown="$refs.search.focusInput()"
+ >
+ <template #toggle>
+ <gl-search-box-by-type
+ ref="search"
+ v-model="searchValue"
+ autofocus
+ debounce="500"
+ @input="handleSearchInput"
+ />
+ </template>
+
+ <template #list-item="{ item }">
+ <component :is="component" :data="item" @select="handleSelectItem" />
+ </template>
+ </gl-collapsible-listbox>
+
+ <component
+ :is="component"
+ v-for="(item, index) of selectedItems"
+ :key="index"
+ :class="{ 'gl-border-t': index > 0 }"
+ class="gl-p-3"
+ :data="item"
+ can-delete
+ @delete="handleDeleteItem"
+ />
+ </gl-card>
+</template>
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 @@
+<script>
+import { GlAvatar, GlButton } from '@gitlab/ui';
+import { sprintf, __ } from '~/locale';
+
+export default {
+ name: 'UserItem',
+ components: {
+ GlAvatar,
+ GlButton,
+ },
+ props: {
+ data: {
+ type: Object,
+ required: true,
+ },
+ canDelete: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ computed: {
+ deleteButtonLabel() {
+ return sprintf(__('Delete %{name}'), { name: this.name });
+ },
+ name() {
+ return this.data.name;
+ },
+ username() {
+ return this.data.username;
+ },
+ avatarUrl() {
+ return this.data.avatarUrl;
+ },
+ },
+};
+</script>
+
+<template>
+ <span class="gl-display-flex gl-align-items-center gl-gap-3" @click="$emit('select', username)">
+ <gl-avatar :alt="name" :size="32" :src="avatarUrl" />
+ <span class="gl-display-flex gl-flex-direction-column gl-flex-grow-1">
+ <span class="gl-font-weight-bold">{{ name }}</span>
+ <span class="gl-text-gray-600">@{{ username }}</span>
+ </span>
+
+ <gl-button
+ v-if="canDelete"
+ icon="remove"
+ :aria-label="deleteButtonLabel"
+ category="tertiary"
+ @click="$emit('delete', username)"
+ />
+ </span>
+</template>
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 |
| ---- | ---- | ----------- |
-| <a id="abusereportpermissionscreatenote"></a>`createNote` | [`Boolean!`](#boolean) | Indicates the user can perform `create_note` on this resource. |
-| <a id="abusereportpermissionsreadabusereport"></a>`readAbuseReport` | [`Boolean!`](#boolean) | Indicates the user can perform `read_abuse_report` on this resource. |
+| <a id="abusereportpermissionscreatenote"></a>`createNote` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_note` on this resource. |
+| <a id="abusereportpermissionsreadabusereport"></a>`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 |
| ---- | ---- | ----------- |
-| <a id="customemojipermissionscreatecustomemoji"></a>`createCustomEmoji` | [`Boolean!`](#boolean) | Indicates the user can perform `create_custom_emoji` on this resource. |
-| <a id="customemojipermissionsdeletecustomemoji"></a>`deleteCustomEmoji` | [`Boolean!`](#boolean) | Indicates the user can perform `delete_custom_emoji` on this resource. |
-| <a id="customemojipermissionsreadcustomemoji"></a>`readCustomEmoji` | [`Boolean!`](#boolean) | Indicates the user can perform `read_custom_emoji` on this resource. |
+| <a id="customemojipermissionscreatecustomemoji"></a>`createCustomEmoji` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_custom_emoji` on this resource. |
+| <a id="customemojipermissionsdeletecustomemoji"></a>`deleteCustomEmoji` | [`Boolean!`](#boolean) | If `true`, the user can perform `delete_custom_emoji` on this resource. |
+| <a id="customemojipermissionsreadcustomemoji"></a>`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 |
| ---- | ---- | ----------- |
-| <a id="dastsiteprofilepermissionscreateondemanddastscan"></a>`createOnDemandDastScan` | [`Boolean!`](#boolean) | Indicates the user can perform `create_on_demand_dast_scan` on this resource. |
+| <a id="dastsiteprofilepermissionscreateondemanddastscan"></a>`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 |
| ---- | ---- | ----------- |
| <a id="deploymentpermissionsapprovedeployment"></a>`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. |
-| <a id="deploymentpermissionsdestroydeployment"></a>`destroyDeployment` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_deployment` on this resource. |
-| <a id="deploymentpermissionsupdatedeployment"></a>`updateDeployment` | [`Boolean!`](#boolean) | Indicates the user can perform `update_deployment` on this resource. |
+| <a id="deploymentpermissionsdestroydeployment"></a>`destroyDeployment` | [`Boolean!`](#boolean) | If `true`, the user can perform `destroy_deployment` on this resource. |
+| <a id="deploymentpermissionsupdatedeployment"></a>`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 |
| ---- | ---- | ----------- |
-| <a id="environmentpermissionsdestroyenvironment"></a>`destroyEnvironment` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_environment` on this resource. |
-| <a id="environmentpermissionsstopenvironment"></a>`stopEnvironment` | [`Boolean!`](#boolean) | Indicates the user can perform `stop_environment` on this resource. |
-| <a id="environmentpermissionsupdateenvironment"></a>`updateEnvironment` | [`Boolean!`](#boolean) | Indicates the user can perform `update_environment` on this resource. |
+| <a id="environmentpermissionsdestroyenvironment"></a>`destroyEnvironment` | [`Boolean!`](#boolean) | If `true`, the user can perform `destroy_environment` on this resource. |
+| <a id="environmentpermissionsstopenvironment"></a>`stopEnvironment` | [`Boolean!`](#boolean) | If `true`, the user can perform `stop_environment` on this resource. |
+| <a id="environmentpermissionsupdateenvironment"></a>`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 |
| ---- | ---- | ----------- |
-| <a id="epicpermissionsadminepic"></a>`adminEpic` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_epic` on this resource. |
-| <a id="epicpermissionsawardemoji"></a>`awardEmoji` | [`Boolean!`](#boolean) | Indicates the user can perform `award_emoji` on this resource. |
-| <a id="epicpermissionscreateepic"></a>`createEpic` | [`Boolean!`](#boolean) | Indicates the user can perform `create_epic` on this resource. |
-| <a id="epicpermissionscreatenote"></a>`createNote` | [`Boolean!`](#boolean) | Indicates the user can perform `create_note` on this resource. |
-| <a id="epicpermissionsdestroyepic"></a>`destroyEpic` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_epic` on this resource. |
-| <a id="epicpermissionsreadepic"></a>`readEpic` | [`Boolean!`](#boolean) | Indicates the user can perform `read_epic` on this resource. |
-| <a id="epicpermissionsreadepiciid"></a>`readEpicIid` | [`Boolean!`](#boolean) | Indicates the user can perform `read_epic_iid` on this resource. |
-| <a id="epicpermissionsupdateepic"></a>`updateEpic` | [`Boolean!`](#boolean) | Indicates the user can perform `update_epic` on this resource. |
+| <a id="epicpermissionsadminepic"></a>`adminEpic` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_epic` on this resource. |
+| <a id="epicpermissionsawardemoji"></a>`awardEmoji` | [`Boolean!`](#boolean) | If `true`, the user can perform `award_emoji` on this resource. |
+| <a id="epicpermissionscreateepic"></a>`createEpic` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_epic` on this resource. |
+| <a id="epicpermissionscreatenote"></a>`createNote` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_note` on this resource. |
+| <a id="epicpermissionsdestroyepic"></a>`destroyEpic` | [`Boolean!`](#boolean) | If `true`, the user can perform `destroy_epic` on this resource. |
+| <a id="epicpermissionsreadepic"></a>`readEpic` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_epic` on this resource. |
+| <a id="epicpermissionsreadepiciid"></a>`readEpicIid` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_epic_iid` on this resource. |
+| <a id="epicpermissionsupdateepic"></a>`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 |
| ---- | ---- | ----------- |
-| <a id="grouppermissionscreatecustomemoji"></a>`createCustomEmoji` | [`Boolean!`](#boolean) | Indicates the user can perform `create_custom_emoji` on this resource. |
-| <a id="grouppermissionscreateprojects"></a>`createProjects` | [`Boolean!`](#boolean) | Indicates the user can perform `create_projects` on this resource. |
-| <a id="grouppermissionsreadgroup"></a>`readGroup` | [`Boolean!`](#boolean) | Indicates the user can perform `read_group` on this resource. |
+| <a id="grouppermissionscreatecustomemoji"></a>`createCustomEmoji` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_custom_emoji` on this resource. |
+| <a id="grouppermissionscreateprojects"></a>`createProjects` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_projects` on this resource. |
+| <a id="grouppermissionsreadgroup"></a>`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 |
| ---- | ---- | ----------- |
-| <a id="issuepermissionsadminissue"></a>`adminIssue` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_issue` on this resource. |
-| <a id="issuepermissionscreatedesign"></a>`createDesign` | [`Boolean!`](#boolean) | Indicates the user can perform `create_design` on this resource. |
-| <a id="issuepermissionscreatenote"></a>`createNote` | [`Boolean!`](#boolean) | Indicates the user can perform `create_note` on this resource. |
-| <a id="issuepermissionsdestroydesign"></a>`destroyDesign` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_design` on this resource. |
-| <a id="issuepermissionsreaddesign"></a>`readDesign` | [`Boolean!`](#boolean) | Indicates the user can perform `read_design` on this resource. |
-| <a id="issuepermissionsreadissue"></a>`readIssue` | [`Boolean!`](#boolean) | Indicates the user can perform `read_issue` on this resource. |
-| <a id="issuepermissionsreopenissue"></a>`reopenIssue` | [`Boolean!`](#boolean) | Indicates the user can perform `reopen_issue` on this resource. |
-| <a id="issuepermissionsupdatedesign"></a>`updateDesign` | [`Boolean!`](#boolean) | Indicates the user can perform `update_design` on this resource. |
-| <a id="issuepermissionsupdateissue"></a>`updateIssue` | [`Boolean!`](#boolean) | Indicates the user can perform `update_issue` on this resource. |
+| <a id="issuepermissionsadminissue"></a>`adminIssue` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_issue` on this resource. |
+| <a id="issuepermissionscreatedesign"></a>`createDesign` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_design` on this resource. |
+| <a id="issuepermissionscreatenote"></a>`createNote` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_note` on this resource. |
+| <a id="issuepermissionsdestroydesign"></a>`destroyDesign` | [`Boolean!`](#boolean) | If `true`, the user can perform `destroy_design` on this resource. |
+| <a id="issuepermissionsreaddesign"></a>`readDesign` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_design` on this resource. |
+| <a id="issuepermissionsreadissue"></a>`readIssue` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_issue` on this resource. |
+| <a id="issuepermissionsreopenissue"></a>`reopenIssue` | [`Boolean!`](#boolean) | If `true`, the user can perform `reopen_issue` on this resource. |
+| <a id="issuepermissionsupdatedesign"></a>`updateDesign` | [`Boolean!`](#boolean) | If `true`, the user can perform `update_design` on this resource. |
+| <a id="issuepermissionsupdateissue"></a>`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 |
| ---- | ---- | ----------- |
-| <a id="jobpermissionsreadbuild"></a>`readBuild` | [`Boolean!`](#boolean) | Indicates the user can perform `read_build` on this resource. |
-| <a id="jobpermissionsreadjobartifacts"></a>`readJobArtifacts` | [`Boolean!`](#boolean) | Indicates the user can perform `read_job_artifacts` on this resource. |
-| <a id="jobpermissionsupdatebuild"></a>`updateBuild` | [`Boolean!`](#boolean) | Indicates the user can perform `update_build` on this resource. |
+| <a id="jobpermissionsreadbuild"></a>`readBuild` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_build` on this resource. |
+| <a id="jobpermissionsreadjobartifacts"></a>`readJobArtifacts` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_job_artifacts` on this resource. |
+| <a id="jobpermissionsupdatebuild"></a>`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 |
| ---- | ---- | ----------- |
-| <a id="mergerequestpermissionsadminmergerequest"></a>`adminMergeRequest` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_merge_request` on this resource. |
-| <a id="mergerequestpermissionscanapprove"></a>`canApprove` | [`Boolean!`](#boolean) | Indicates the user can perform `can_approve` on this resource. |
-| <a id="mergerequestpermissionscanmerge"></a>`canMerge` | [`Boolean!`](#boolean) | Indicates the user can perform `can_merge` on this resource. |
-| <a id="mergerequestpermissionscherrypickoncurrentmergerequest"></a>`cherryPickOnCurrentMergeRequest` | [`Boolean!`](#boolean) | Indicates the user can perform `cherry_pick_on_current_merge_request` on this resource. |
-| <a id="mergerequestpermissionscreatenote"></a>`createNote` | [`Boolean!`](#boolean) | Indicates the user can perform `create_note` on this resource. |
-| <a id="mergerequestpermissionspushtosourcebranch"></a>`pushToSourceBranch` | [`Boolean!`](#boolean) | Indicates the user can perform `push_to_source_branch` on this resource. |
-| <a id="mergerequestpermissionsreadmergerequest"></a>`readMergeRequest` | [`Boolean!`](#boolean) | Indicates the user can perform `read_merge_request` on this resource. |
-| <a id="mergerequestpermissionsremovesourcebranch"></a>`removeSourceBranch` | [`Boolean!`](#boolean) | Indicates the user can perform `remove_source_branch` on this resource. |
-| <a id="mergerequestpermissionsrevertoncurrentmergerequest"></a>`revertOnCurrentMergeRequest` | [`Boolean!`](#boolean) | Indicates the user can perform `revert_on_current_merge_request` on this resource. |
-| <a id="mergerequestpermissionsupdatemergerequest"></a>`updateMergeRequest` | [`Boolean!`](#boolean) | Indicates the user can perform `update_merge_request` on this resource. |
+| <a id="mergerequestpermissionsadminmergerequest"></a>`adminMergeRequest` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_merge_request` on this resource. |
+| <a id="mergerequestpermissionscanapprove"></a>`canApprove` | [`Boolean!`](#boolean) | If `true`, the user can perform `can_approve` on this resource. |
+| <a id="mergerequestpermissionscanmerge"></a>`canMerge` | [`Boolean!`](#boolean) | If `true`, the user can perform `can_merge` on this resource. |
+| <a id="mergerequestpermissionscherrypickoncurrentmergerequest"></a>`cherryPickOnCurrentMergeRequest` | [`Boolean!`](#boolean) | If `true`, the user can perform `cherry_pick_on_current_merge_request` on this resource. |
+| <a id="mergerequestpermissionscreatenote"></a>`createNote` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_note` on this resource. |
+| <a id="mergerequestpermissionspushtosourcebranch"></a>`pushToSourceBranch` | [`Boolean!`](#boolean) | If `true`, the user can perform `push_to_source_branch` on this resource. |
+| <a id="mergerequestpermissionsreadmergerequest"></a>`readMergeRequest` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_merge_request` on this resource. |
+| <a id="mergerequestpermissionsremovesourcebranch"></a>`removeSourceBranch` | [`Boolean!`](#boolean) | If `true`, the user can perform `remove_source_branch` on this resource. |
+| <a id="mergerequestpermissionsrevertoncurrentmergerequest"></a>`revertOnCurrentMergeRequest` | [`Boolean!`](#boolean) | If `true`, the user can perform `revert_on_current_merge_request` on this resource. |
+| <a id="mergerequestpermissionsupdatemergerequest"></a>`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 |
| ---- | ---- | ----------- |
-| <a id="notepermissionsadminnote"></a>`adminNote` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_note` on this resource. |
-| <a id="notepermissionsawardemoji"></a>`awardEmoji` | [`Boolean!`](#boolean) | Indicates the user can perform `award_emoji` on this resource. |
-| <a id="notepermissionscreatenote"></a>`createNote` | [`Boolean!`](#boolean) | Indicates the user can perform `create_note` on this resource. |
-| <a id="notepermissionsreadnote"></a>`readNote` | [`Boolean!`](#boolean) | Indicates the user can perform `read_note` on this resource. |
-| <a id="notepermissionsrepositionnote"></a>`repositionNote` | [`Boolean!`](#boolean) | Indicates the user can perform `reposition_note` on this resource. |
-| <a id="notepermissionsresolvenote"></a>`resolveNote` | [`Boolean!`](#boolean) | Indicates the user can perform `resolve_note` on this resource. |
+| <a id="notepermissionsadminnote"></a>`adminNote` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_note` on this resource. |
+| <a id="notepermissionsawardemoji"></a>`awardEmoji` | [`Boolean!`](#boolean) | If `true`, the user can perform `award_emoji` on this resource. |
+| <a id="notepermissionscreatenote"></a>`createNote` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_note` on this resource. |
+| <a id="notepermissionsreadnote"></a>`readNote` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_note` on this resource. |
+| <a id="notepermissionsrepositionnote"></a>`repositionNote` | [`Boolean!`](#boolean) | If `true`, the user can perform `reposition_note` on this resource. |
+| <a id="notepermissionsresolvenote"></a>`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 |
| ---- | ---- | ----------- |
-| <a id="pipelinepermissionsadminpipeline"></a>`adminPipeline` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_pipeline` on this resource. |
-| <a id="pipelinepermissionsdestroypipeline"></a>`destroyPipeline` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_pipeline` on this resource. |
-| <a id="pipelinepermissionsupdatepipeline"></a>`updatePipeline` | [`Boolean!`](#boolean) | Indicates the user can perform `update_pipeline` on this resource. |
+| <a id="pipelinepermissionsadminpipeline"></a>`adminPipeline` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_pipeline` on this resource. |
+| <a id="pipelinepermissionsdestroypipeline"></a>`destroyPipeline` | [`Boolean!`](#boolean) | If `true`, the user can perform `destroy_pipeline` on this resource. |
+| <a id="pipelinepermissionsupdatepipeline"></a>`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 |
| ---- | ---- | ----------- |
-| <a id="pipelineschedulepermissionsadminpipelineschedule"></a>`adminPipelineSchedule` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_pipeline_schedule` on this resource. |
-| <a id="pipelineschedulepermissionsplaypipelineschedule"></a>`playPipelineSchedule` | [`Boolean!`](#boolean) | Indicates the user can perform `play_pipeline_schedule` on this resource. |
+| <a id="pipelineschedulepermissionsadminpipelineschedule"></a>`adminPipelineSchedule` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_pipeline_schedule` on this resource. |
+| <a id="pipelineschedulepermissionsplaypipelineschedule"></a>`playPipelineSchedule` | [`Boolean!`](#boolean) | If `true`, the user can perform `play_pipeline_schedule` on this resource. |
| <a id="pipelineschedulepermissionstakeownershippipelineschedule"></a>`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. |
-| <a id="pipelineschedulepermissionsupdatepipelineschedule"></a>`updatePipelineSchedule` | [`Boolean!`](#boolean) | Indicates the user can perform `update_pipeline_schedule` on this resource. |
+| <a id="pipelineschedulepermissionsupdatepipelineschedule"></a>`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 |
| ---- | ---- | ----------- |
-| <a id="projectpermissionsadminoperations"></a>`adminOperations` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_operations` on this resource. |
-| <a id="projectpermissionsadminpathlocks"></a>`adminPathLocks` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_path_locks` on this resource. |
-| <a id="projectpermissionsadminproject"></a>`adminProject` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_project` on this resource. |
-| <a id="projectpermissionsadminremotemirror"></a>`adminRemoteMirror` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_remote_mirror` on this resource. |
-| <a id="projectpermissionsadminwiki"></a>`adminWiki` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_wiki` on this resource. |
-| <a id="projectpermissionsarchiveproject"></a>`archiveProject` | [`Boolean!`](#boolean) | Indicates the user can perform `archive_project` on this resource. |
-| <a id="projectpermissionschangenamespace"></a>`changeNamespace` | [`Boolean!`](#boolean) | Indicates the user can perform `change_namespace` on this resource. |
-| <a id="projectpermissionschangevisibilitylevel"></a>`changeVisibilityLevel` | [`Boolean!`](#boolean) | Indicates the user can perform `change_visibility_level` on this resource. |
-| <a id="projectpermissionscreatedeployment"></a>`createDeployment` | [`Boolean!`](#boolean) | Indicates the user can perform `create_deployment` on this resource. |
-| <a id="projectpermissionscreatedesign"></a>`createDesign` | [`Boolean!`](#boolean) | Indicates the user can perform `create_design` on this resource. |
-| <a id="projectpermissionscreateissue"></a>`createIssue` | [`Boolean!`](#boolean) | Indicates the user can perform `create_issue` on this resource. |
-| <a id="projectpermissionscreatelabel"></a>`createLabel` | [`Boolean!`](#boolean) | Indicates the user can perform `create_label` on this resource. |
-| <a id="projectpermissionscreatemergerequestfrom"></a>`createMergeRequestFrom` | [`Boolean!`](#boolean) | Indicates the user can perform `create_merge_request_from` on this resource. |
-| <a id="projectpermissionscreatemergerequestin"></a>`createMergeRequestIn` | [`Boolean!`](#boolean) | Indicates the user can perform `create_merge_request_in` on this resource. |
-| <a id="projectpermissionscreatepages"></a>`createPages` | [`Boolean!`](#boolean) | Indicates the user can perform `create_pages` on this resource. |
-| <a id="projectpermissionscreatepipeline"></a>`createPipeline` | [`Boolean!`](#boolean) | Indicates the user can perform `create_pipeline` on this resource. |
-| <a id="projectpermissionscreatepipelineschedule"></a>`createPipelineSchedule` | [`Boolean!`](#boolean) | Indicates the user can perform `create_pipeline_schedule` on this resource. |
-| <a id="projectpermissionscreatesnippet"></a>`createSnippet` | [`Boolean!`](#boolean) | Indicates the user can perform `create_snippet` on this resource. |
-| <a id="projectpermissionscreatewiki"></a>`createWiki` | [`Boolean!`](#boolean) | Indicates the user can perform `create_wiki` on this resource. |
-| <a id="projectpermissionsdestroydesign"></a>`destroyDesign` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_design` on this resource. |
-| <a id="projectpermissionsdestroypages"></a>`destroyPages` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_pages` on this resource. |
-| <a id="projectpermissionsdestroywiki"></a>`destroyWiki` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_wiki` on this resource. |
-| <a id="projectpermissionsdownloadcode"></a>`downloadCode` | [`Boolean!`](#boolean) | Indicates the user can perform `download_code` on this resource. |
-| <a id="projectpermissionsdownloadwikicode"></a>`downloadWikiCode` | [`Boolean!`](#boolean) | Indicates the user can perform `download_wiki_code` on this resource. |
-| <a id="projectpermissionsforkproject"></a>`forkProject` | [`Boolean!`](#boolean) | Indicates the user can perform `fork_project` on this resource. |
-| <a id="projectpermissionspushcode"></a>`pushCode` | [`Boolean!`](#boolean) | Indicates the user can perform `push_code` on this resource. |
-| <a id="projectpermissionspushtodeleteprotectedbranch"></a>`pushToDeleteProtectedBranch` | [`Boolean!`](#boolean) | Indicates the user can perform `push_to_delete_protected_branch` on this resource. |
-| <a id="projectpermissionsreadcommitstatus"></a>`readCommitStatus` | [`Boolean!`](#boolean) | Indicates the user can perform `read_commit_status` on this resource. |
-| <a id="projectpermissionsreadcycleanalytics"></a>`readCycleAnalytics` | [`Boolean!`](#boolean) | Indicates the user can perform `read_cycle_analytics` on this resource. |
-| <a id="projectpermissionsreaddesign"></a>`readDesign` | [`Boolean!`](#boolean) | Indicates the user can perform `read_design` on this resource. |
-| <a id="projectpermissionsreadenvironment"></a>`readEnvironment` | [`Boolean!`](#boolean) | Indicates the user can perform `read_environment` on this resource. |
-| <a id="projectpermissionsreadmergerequest"></a>`readMergeRequest` | [`Boolean!`](#boolean) | Indicates the user can perform `read_merge_request` on this resource. |
-| <a id="projectpermissionsreadpagescontent"></a>`readPagesContent` | [`Boolean!`](#boolean) | Indicates the user can perform `read_pages_content` on this resource. |
-| <a id="projectpermissionsreadproject"></a>`readProject` | [`Boolean!`](#boolean) | Indicates the user can perform `read_project` on this resource. |
-| <a id="projectpermissionsreadprojectmember"></a>`readProjectMember` | [`Boolean!`](#boolean) | Indicates the user can perform `read_project_member` on this resource. |
-| <a id="projectpermissionsreadwiki"></a>`readWiki` | [`Boolean!`](#boolean) | Indicates the user can perform `read_wiki` on this resource. |
-| <a id="projectpermissionsremoveforkproject"></a>`removeForkProject` | [`Boolean!`](#boolean) | Indicates the user can perform `remove_fork_project` on this resource. |
-| <a id="projectpermissionsremovepages"></a>`removePages` | [`Boolean!`](#boolean) | Indicates the user can perform `remove_pages` on this resource. |
-| <a id="projectpermissionsremoveproject"></a>`removeProject` | [`Boolean!`](#boolean) | Indicates the user can perform `remove_project` on this resource. |
-| <a id="projectpermissionsrenameproject"></a>`renameProject` | [`Boolean!`](#boolean) | Indicates the user can perform `rename_project` on this resource. |
-| <a id="projectpermissionsrequestaccess"></a>`requestAccess` | [`Boolean!`](#boolean) | Indicates the user can perform `request_access` on this resource. |
-| <a id="projectpermissionsupdatepages"></a>`updatePages` | [`Boolean!`](#boolean) | Indicates the user can perform `update_pages` on this resource. |
-| <a id="projectpermissionsupdatewiki"></a>`updateWiki` | [`Boolean!`](#boolean) | Indicates the user can perform `update_wiki` on this resource. |
-| <a id="projectpermissionsuploadfile"></a>`uploadFile` | [`Boolean!`](#boolean) | Indicates the user can perform `upload_file` on this resource. |
+| <a id="projectpermissionsadminoperations"></a>`adminOperations` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_operations` on this resource. |
+| <a id="projectpermissionsadminpathlocks"></a>`adminPathLocks` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_path_locks` on this resource. |
+| <a id="projectpermissionsadminproject"></a>`adminProject` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_project` on this resource. |
+| <a id="projectpermissionsadminremotemirror"></a>`adminRemoteMirror` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_remote_mirror` on this resource. |
+| <a id="projectpermissionsadminwiki"></a>`adminWiki` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_wiki` on this resource. |
+| <a id="projectpermissionsarchiveproject"></a>`archiveProject` | [`Boolean!`](#boolean) | If `true`, the user can perform `archive_project` on this resource. |
+| <a id="projectpermissionschangenamespace"></a>`changeNamespace` | [`Boolean!`](#boolean) | If `true`, the user can perform `change_namespace` on this resource. |
+| <a id="projectpermissionschangevisibilitylevel"></a>`changeVisibilityLevel` | [`Boolean!`](#boolean) | If `true`, the user can perform `change_visibility_level` on this resource. |
+| <a id="projectpermissionscreatedeployment"></a>`createDeployment` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_deployment` on this resource. |
+| <a id="projectpermissionscreatedesign"></a>`createDesign` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_design` on this resource. |
+| <a id="projectpermissionscreateissue"></a>`createIssue` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_issue` on this resource. |
+| <a id="projectpermissionscreatelabel"></a>`createLabel` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_label` on this resource. |
+| <a id="projectpermissionscreatemergerequestfrom"></a>`createMergeRequestFrom` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_merge_request_from` on this resource. |
+| <a id="projectpermissionscreatemergerequestin"></a>`createMergeRequestIn` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_merge_request_in` on this resource. |
+| <a id="projectpermissionscreatepages"></a>`createPages` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_pages` on this resource. |
+| <a id="projectpermissionscreatepipeline"></a>`createPipeline` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_pipeline` on this resource. |
+| <a id="projectpermissionscreatepipelineschedule"></a>`createPipelineSchedule` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_pipeline_schedule` on this resource. |
+| <a id="projectpermissionscreatesnippet"></a>`createSnippet` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_snippet` on this resource. |
+| <a id="projectpermissionscreatewiki"></a>`createWiki` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_wiki` on this resource. |
+| <a id="projectpermissionsdestroydesign"></a>`destroyDesign` | [`Boolean!`](#boolean) | If `true`, the user can perform `destroy_design` on this resource. |
+| <a id="projectpermissionsdestroypages"></a>`destroyPages` | [`Boolean!`](#boolean) | If `true`, the user can perform `destroy_pages` on this resource. |
+| <a id="projectpermissionsdestroywiki"></a>`destroyWiki` | [`Boolean!`](#boolean) | If `true`, the user can perform `destroy_wiki` on this resource. |
+| <a id="projectpermissionsdownloadcode"></a>`downloadCode` | [`Boolean!`](#boolean) | If `true`, the user can perform `download_code` on this resource. |
+| <a id="projectpermissionsdownloadwikicode"></a>`downloadWikiCode` | [`Boolean!`](#boolean) | If `true`, the user can perform `download_wiki_code` on this resource. |
+| <a id="projectpermissionsforkproject"></a>`forkProject` | [`Boolean!`](#boolean) | If `true`, the user can perform `fork_project` on this resource. |
+| <a id="projectpermissionspushcode"></a>`pushCode` | [`Boolean!`](#boolean) | If `true`, the user can perform `push_code` on this resource. |
+| <a id="projectpermissionspushtodeleteprotectedbranch"></a>`pushToDeleteProtectedBranch` | [`Boolean!`](#boolean) | If `true`, the user can perform `push_to_delete_protected_branch` on this resource. |
+| <a id="projectpermissionsreadcommitstatus"></a>`readCommitStatus` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_commit_status` on this resource. |
+| <a id="projectpermissionsreadcycleanalytics"></a>`readCycleAnalytics` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_cycle_analytics` on this resource. |
+| <a id="projectpermissionsreaddesign"></a>`readDesign` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_design` on this resource. |
+| <a id="projectpermissionsreadenvironment"></a>`readEnvironment` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_environment` on this resource. |
+| <a id="projectpermissionsreadmergerequest"></a>`readMergeRequest` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_merge_request` on this resource. |
+| <a id="projectpermissionsreadpagescontent"></a>`readPagesContent` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_pages_content` on this resource. |
+| <a id="projectpermissionsreadproject"></a>`readProject` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_project` on this resource. |
+| <a id="projectpermissionsreadprojectmember"></a>`readProjectMember` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_project_member` on this resource. |
+| <a id="projectpermissionsreadwiki"></a>`readWiki` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_wiki` on this resource. |
+| <a id="projectpermissionsremoveforkproject"></a>`removeForkProject` | [`Boolean!`](#boolean) | If `true`, the user can perform `remove_fork_project` on this resource. |
+| <a id="projectpermissionsremovepages"></a>`removePages` | [`Boolean!`](#boolean) | If `true`, the user can perform `remove_pages` on this resource. |
+| <a id="projectpermissionsremoveproject"></a>`removeProject` | [`Boolean!`](#boolean) | If `true`, the user can perform `remove_project` on this resource. |
+| <a id="projectpermissionsrenameproject"></a>`renameProject` | [`Boolean!`](#boolean) | If `true`, the user can perform `rename_project` on this resource. |
+| <a id="projectpermissionsrequestaccess"></a>`requestAccess` | [`Boolean!`](#boolean) | If `true`, the user can perform `request_access` on this resource. |
+| <a id="projectpermissionsupdatepages"></a>`updatePages` | [`Boolean!`](#boolean) | If `true`, the user can perform `update_pages` on this resource. |
+| <a id="projectpermissionsupdatewiki"></a>`updateWiki` | [`Boolean!`](#boolean) | If `true`, the user can perform `update_wiki` on this resource. |
+| <a id="projectpermissionsuploadfile"></a>`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 |
| ---- | ---- | ----------- |
-| <a id="requirementpermissionsadminrequirement"></a>`adminRequirement` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_requirement` on this resource. |
-| <a id="requirementpermissionscreaterequirement"></a>`createRequirement` | [`Boolean!`](#boolean) | Indicates the user can perform `create_requirement` on this resource. |
-| <a id="requirementpermissionsdestroyrequirement"></a>`destroyRequirement` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_requirement` on this resource. |
-| <a id="requirementpermissionsreadrequirement"></a>`readRequirement` | [`Boolean!`](#boolean) | Indicates the user can perform `read_requirement` on this resource. |
-| <a id="requirementpermissionsupdaterequirement"></a>`updateRequirement` | [`Boolean!`](#boolean) | Indicates the user can perform `update_requirement` on this resource. |
+| <a id="requirementpermissionsadminrequirement"></a>`adminRequirement` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_requirement` on this resource. |
+| <a id="requirementpermissionscreaterequirement"></a>`createRequirement` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_requirement` on this resource. |
+| <a id="requirementpermissionsdestroyrequirement"></a>`destroyRequirement` | [`Boolean!`](#boolean) | If `true`, the user can perform `destroy_requirement` on this resource. |
+| <a id="requirementpermissionsreadrequirement"></a>`readRequirement` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_requirement` on this resource. |
+| <a id="requirementpermissionsupdaterequirement"></a>`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 |
| ---- | ---- | ----------- |
-| <a id="runnerpermissionsassignrunner"></a>`assignRunner` | [`Boolean!`](#boolean) | Indicates the user can perform `assign_runner` on this resource. |
-| <a id="runnerpermissionsdeleterunner"></a>`deleteRunner` | [`Boolean!`](#boolean) | Indicates the user can perform `delete_runner` on this resource. |
-| <a id="runnerpermissionsreadrunner"></a>`readRunner` | [`Boolean!`](#boolean) | Indicates the user can perform `read_runner` on this resource. |
-| <a id="runnerpermissionsupdaterunner"></a>`updateRunner` | [`Boolean!`](#boolean) | Indicates the user can perform `update_runner` on this resource. |
+| <a id="runnerpermissionsassignrunner"></a>`assignRunner` | [`Boolean!`](#boolean) | If `true`, the user can perform `assign_runner` on this resource. |
+| <a id="runnerpermissionsdeleterunner"></a>`deleteRunner` | [`Boolean!`](#boolean) | If `true`, the user can perform `delete_runner` on this resource. |
+| <a id="runnerpermissionsreadrunner"></a>`readRunner` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_runner` on this resource. |
+| <a id="runnerpermissionsupdaterunner"></a>`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 |
| ---- | ---- | ----------- |
-| <a id="snippetpermissionsadminsnippet"></a>`adminSnippet` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_snippet` on this resource. |
-| <a id="snippetpermissionsawardemoji"></a>`awardEmoji` | [`Boolean!`](#boolean) | Indicates the user can perform `award_emoji` on this resource. |
-| <a id="snippetpermissionscreatenote"></a>`createNote` | [`Boolean!`](#boolean) | Indicates the user can perform `create_note` on this resource. |
-| <a id="snippetpermissionsreadsnippet"></a>`readSnippet` | [`Boolean!`](#boolean) | Indicates the user can perform `read_snippet` on this resource. |
-| <a id="snippetpermissionsreportsnippet"></a>`reportSnippet` | [`Boolean!`](#boolean) | Indicates the user can perform `report_snippet` on this resource. |
-| <a id="snippetpermissionsupdatesnippet"></a>`updateSnippet` | [`Boolean!`](#boolean) | Indicates the user can perform `update_snippet` on this resource. |
+| <a id="snippetpermissionsadminsnippet"></a>`adminSnippet` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_snippet` on this resource. |
+| <a id="snippetpermissionsawardemoji"></a>`awardEmoji` | [`Boolean!`](#boolean) | If `true`, the user can perform `award_emoji` on this resource. |
+| <a id="snippetpermissionscreatenote"></a>`createNote` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_note` on this resource. |
+| <a id="snippetpermissionsreadsnippet"></a>`readSnippet` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_snippet` on this resource. |
+| <a id="snippetpermissionsreportsnippet"></a>`reportSnippet` | [`Boolean!`](#boolean) | If `true`, the user can perform `report_snippet` on this resource. |
+| <a id="snippetpermissionsupdatesnippet"></a>`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 |
| ---- | ---- | ----------- |
-| <a id="timelogpermissionsadmintimelog"></a>`adminTimelog` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_timelog` on this resource. |
+| <a id="timelogpermissionsadmintimelog"></a>`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 |
| ---- | ---- | ----------- |
-| <a id="userpermissionscreatesnippet"></a>`createSnippet` | [`Boolean!`](#boolean) | Indicates the user can perform `create_snippet` on this resource. |
+| <a id="userpermissionscreatesnippet"></a>`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 |
| ---- | ---- | ----------- |
-| <a id="vulnerabilitypermissionsadminvulnerability"></a>`adminVulnerability` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_vulnerability` on this resource. |
-| <a id="vulnerabilitypermissionsadminvulnerabilityexternalissuelink"></a>`adminVulnerabilityExternalIssueLink` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_vulnerability_external_issue_link` on this resource. |
-| <a id="vulnerabilitypermissionsadminvulnerabilityissuelink"></a>`adminVulnerabilityIssueLink` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_vulnerability_issue_link` on this resource. |
-| <a id="vulnerabilitypermissionscreatevulnerabilityexport"></a>`createVulnerabilityExport` | [`Boolean!`](#boolean) | Indicates the user can perform `create_vulnerability_export` on this resource. |
-| <a id="vulnerabilitypermissionscreatevulnerabilityfeedback"></a>`createVulnerabilityFeedback` | [`Boolean!`](#boolean) | Indicates the user can perform `create_vulnerability_feedback` on this resource. |
-| <a id="vulnerabilitypermissionsdestroyvulnerabilityfeedback"></a>`destroyVulnerabilityFeedback` | [`Boolean!`](#boolean) | Indicates the user can perform `destroy_vulnerability_feedback` on this resource. |
-| <a id="vulnerabilitypermissionsreadvulnerability"></a>`readVulnerability` | [`Boolean!`](#boolean) | Indicates the user can perform `read_vulnerability` on this resource. |
-| <a id="vulnerabilitypermissionsreadvulnerabilityfeedback"></a>`readVulnerabilityFeedback` | [`Boolean!`](#boolean) | Indicates the user can perform `read_vulnerability_feedback` on this resource. |
-| <a id="vulnerabilitypermissionsupdatevulnerabilityfeedback"></a>`updateVulnerabilityFeedback` | [`Boolean!`](#boolean) | Indicates the user can perform `update_vulnerability_feedback` on this resource. |
+| <a id="vulnerabilitypermissionsadminvulnerability"></a>`adminVulnerability` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_vulnerability` on this resource. |
+| <a id="vulnerabilitypermissionsadminvulnerabilityexternalissuelink"></a>`adminVulnerabilityExternalIssueLink` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_vulnerability_external_issue_link` on this resource. |
+| <a id="vulnerabilitypermissionsadminvulnerabilityissuelink"></a>`adminVulnerabilityIssueLink` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_vulnerability_issue_link` on this resource. |
+| <a id="vulnerabilitypermissionscreatevulnerabilityexport"></a>`createVulnerabilityExport` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_vulnerability_export` on this resource. |
+| <a id="vulnerabilitypermissionscreatevulnerabilityfeedback"></a>`createVulnerabilityFeedback` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_vulnerability_feedback` on this resource. |
+| <a id="vulnerabilitypermissionsdestroyvulnerabilityfeedback"></a>`destroyVulnerabilityFeedback` | [`Boolean!`](#boolean) | If `true`, the user can perform `destroy_vulnerability_feedback` on this resource. |
+| <a id="vulnerabilitypermissionsreadvulnerability"></a>`readVulnerability` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_vulnerability` on this resource. |
+| <a id="vulnerabilitypermissionsreadvulnerabilityfeedback"></a>`readVulnerabilityFeedback` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_vulnerability_feedback` on this resource. |
+| <a id="vulnerabilitypermissionsupdatevulnerabilityfeedback"></a>`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 |
| ---- | ---- | ----------- |
-| <a id="workitempermissionsadminparentlink"></a>`adminParentLink` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_parent_link` on this resource. |
-| <a id="workitempermissionsadminworkitem"></a>`adminWorkItem` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_work_item` on this resource. |
-| <a id="workitempermissionsadminworkitemlink"></a>`adminWorkItemLink` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_work_item_link` on this resource. |
-| <a id="workitempermissionscreatenote"></a>`createNote` | [`Boolean!`](#boolean) | Indicates the user can perform `create_note` on this resource. |
-| <a id="workitempermissionsdeleteworkitem"></a>`deleteWorkItem` | [`Boolean!`](#boolean) | Indicates the user can perform `delete_work_item` on this resource. |
-| <a id="workitempermissionsreadworkitem"></a>`readWorkItem` | [`Boolean!`](#boolean) | Indicates the user can perform `read_work_item` on this resource. |
-| <a id="workitempermissionssetworkitemmetadata"></a>`setWorkItemMetadata` | [`Boolean!`](#boolean) | Indicates the user can perform `set_work_item_metadata` on this resource. |
-| <a id="workitempermissionsupdateworkitem"></a>`updateWorkItem` | [`Boolean!`](#boolean) | Indicates the user can perform `update_work_item` on this resource. |
+| <a id="workitempermissionsadminparentlink"></a>`adminParentLink` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_parent_link` on this resource. |
+| <a id="workitempermissionsadminworkitem"></a>`adminWorkItem` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_work_item` on this resource. |
+| <a id="workitempermissionsadminworkitemlink"></a>`adminWorkItemLink` | [`Boolean!`](#boolean) | If `true`, the user can perform `admin_work_item_link` on this resource. |
+| <a id="workitempermissionscreatenote"></a>`createNote` | [`Boolean!`](#boolean) | If `true`, the user can perform `create_note` on this resource. |
+| <a id="workitempermissionsdeleteworkitem"></a>`deleteWorkItem` | [`Boolean!`](#boolean) | If `true`, the user can perform `delete_work_item` on this resource. |
+| <a id="workitempermissionsreadworkitem"></a>`readWorkItem` | [`Boolean!`](#boolean) | If `true`, the user can perform `read_work_item` on this resource. |
+| <a id="workitempermissionssetworkitemmetadata"></a>`setWorkItemMetadata` | [`Boolean!`](#boolean) | If `true`, the user can perform `set_work_item_metadata` on this resource. |
+| <a id="workitempermissionsupdateworkitem"></a>`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 `<http|https>://<GitLab host>/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 `<http|https>://<GitLab host>/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 `<http|https>://<GitLab host>/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 ||= %(<build branchName=\"#{branch}\"><buildType id=\"foo\"/></build>)
- 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_helpers.rb
index 1c9fce183e9..1c9fce183e9 100644
--- a/spec/support/helpers/packages_manager_api_spec_helper.rb
+++ b/spec/support/helpers/packages_manager_api_spec_helpers.rb
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 <host>:<port> 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)
+ })
+ }
+}