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-13 03:10:17 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-10-13 03:10:17 +0300
commitdce8d0c6a7fdc7cca4df3b00b11d68000d117e2f (patch)
treeae6060a584549cfcecced34eea93e2b4fe5c64ed
parent74cb1a1df361969e97d1a85683c1dfca5ac8cad1 (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.checksum2
-rw-r--r--Gemfile.lock4
-rw-r--r--app/assets/javascripts/super_sidebar/components/user_menu.vue9
-rw-r--r--app/assets/javascripts/super_sidebar/components/user_menu_profile_item.vue83
-rw-r--r--app/assets/javascripts/super_sidebar/components/user_name_group.vue91
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/action_buttons.vue8
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue1
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue8
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/sha_mismatch.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/widget/action_buttons.vue7
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/header.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue6
-rw-r--r--app/models/packages/protection/rule.rb10
-rw-r--r--config/feature_flags/development/prohibited_tag_name_encoding_check.yml (renamed from config/feature_flags/development/on_demand_scans_runner_tags.yml)12
-rw-r--r--db/migrate/20231010101246_change_push_protected_up_to_access_level_to_smallint_in_packages_protection_rules.rb13
-rw-r--r--db/schema_migrations/202310101012461
-rw-r--r--db/structure.sql2
-rw-r--r--doc/administration/audit_event_streaming/graphql_api.md22
-rw-r--r--doc/user/application_security/dast/proxy-based.md1
-rw-r--r--doc/user/project/repository/managing_large_repositories.md46
-rw-r--r--lib/api/entities/bulk_import.rb1
-rw-r--r--lib/api/entities/bulk_imports/entity.rb1
-rw-r--r--lib/gitlab/checks/tag_check.rb13
-rw-r--r--lib/gitlab/encoding_helper.rb4
-rw-r--r--qa/qa/page/main/menu.rb2
-rw-r--r--qa/qa/page/merge_request/show.rb76
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/ci_project_artifacts/user_can_bulk_delete_artifacts_spec.rb4
-rw-r--r--spec/factories/packages/protection/rules.rb2
-rw-r--r--spec/frontend/design_management/pages/index_spec.js2
-rw-r--r--spec/frontend/super_sidebar/components/user_menu_profile_item_spec.js (renamed from spec/frontend/super_sidebar/components/user_name_group_spec.js)13
-rw-r--r--spec/frontend/super_sidebar/components/user_menu_spec.js8
-rw-r--r--spec/frontend/work_items/components/work_item_links/work_item_links_spec.js1
-rw-r--r--spec/lib/api/entities/bulk_import_spec.rb5
-rw-r--r--spec/lib/api/entities/bulk_imports/entity_spec.rb5
-rw-r--r--spec/lib/gitlab/checks/tag_check_spec.rb30
-rw-r--r--spec/lib/gitlab/encoding_helper_spec.rb37
-rw-r--r--spec/models/packages/protection/rule_spec.rb21
42 files changed, 343 insertions, 228 deletions
diff --git a/Gemfile b/Gemfile
index 15e1aff2edf..dd902996341 100644
--- a/Gemfile
+++ b/Gemfile
@@ -530,7 +530,7 @@ gem 'ssh_data', '~> 1.3' # rubocop:todo Gemfile/MissingFeatureCategory
gem 'spamcheck', '~> 1.3.0' # rubocop:todo Gemfile/MissingFeatureCategory
# Gitaly GRPC protocol definitions
-gem 'gitaly', '~> 16.3.0-rc1' # rubocop:todo Gemfile/MissingFeatureCategory
+gem 'gitaly', '~> 16.5.0.pre.rc1' # rubocop:todo Gemfile/MissingFeatureCategory
# KAS GRPC protocol definitions
gem 'kas-grpc', '~> 0.2.0' # rubocop:todo Gemfile/MissingFeatureCategory
diff --git a/Gemfile.checksum b/Gemfile.checksum
index 8d7326c7821..8397f016bac 100644
--- a/Gemfile.checksum
+++ b/Gemfile.checksum
@@ -203,7 +203,7 @@
{"name":"gettext_i18n_rails","version":"1.11.0","platform":"ruby","checksum":"e19c7e4a256c500f7f38396dca44a282b9838ae278f57c362993a54964b22bbe"},
{"name":"gettext_i18n_rails_js","version":"1.3.0","platform":"ruby","checksum":"5d10afe4be3639bff78c50a56768c20f39aecdabc580c08aa45573911c2bd687"},
{"name":"git","version":"1.18.0","platform":"ruby","checksum":"c9b80462e4565cd3d7a9ba8440c41d2c52244b17b0dad0bfddb46de70630c465"},
-{"name":"gitaly","version":"16.3.0.pre.rc1","platform":"ruby","checksum":"55d9cc414a4f3859588f3770bd88d7c67c0f5454a1178b018b7a6f6913674c43"},
+{"name":"gitaly","version":"16.5.0.pre.rc1","platform":"ruby","checksum":"ed17515ad04d4663a0efc15c8f2887b705f006133e8b10cc9321460eb0a38353"},
{"name":"gitlab","version":"4.19.0","platform":"ruby","checksum":"3f645e3e195dbc24f0834fbf83e8ccfb2056d8e9712b01a640aad418a6949679"},
{"name":"gitlab-chronic","version":"0.10.5","platform":"ruby","checksum":"f80f18dc699b708870a80685243331290bc10cfeedb6b99c92219722f729c875"},
{"name":"gitlab-dangerfiles","version":"4.1.0","platform":"ruby","checksum":"ecf2262fcc038c1e77f7ea014f5fa8657e02ae37fde5034a2d7f67fd6e804d8d"},
diff --git a/Gemfile.lock b/Gemfile.lock
index 51101a25079..77e936d8bc0 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -639,7 +639,7 @@ GEM
git (1.18.0)
addressable (~> 2.8)
rchardet (~> 1.8)
- gitaly (16.3.0.pre.rc1)
+ gitaly (16.5.0.pre.rc1)
grpc (~> 1.0)
gitlab (4.19.0)
httparty (~> 0.20)
@@ -1816,7 +1816,7 @@ DEPENDENCIES
gettext (~> 3.3)
gettext_i18n_rails (~> 1.11.0)
gettext_i18n_rails_js (~> 1.3)
- gitaly (~> 16.3.0.pre.rc1)
+ gitaly (~> 16.5.0.pre.rc1)
gitlab-chronic (~> 0.10.5)
gitlab-dangerfiles (~> 4.1.0)
gitlab-experiment (~> 0.8.0)
diff --git a/app/assets/javascripts/super_sidebar/components/user_menu.vue b/app/assets/javascripts/super_sidebar/components/user_menu.vue
index ed6c41e85c6..891e883b6c0 100644
--- a/app/assets/javascripts/super_sidebar/components/user_menu.vue
+++ b/app/assets/javascripts/super_sidebar/components/user_menu.vue
@@ -12,7 +12,7 @@ import NewNavToggle from '~/nav/components/new_nav_toggle.vue';
import Tracking from '~/tracking';
import PersistentUserCallout from '~/persistent_user_callout';
import { USER_MENU_TRACKING_DEFAULTS, DROPDOWN_Y_OFFSET, IMPERSONATING_OFFSET } from '../constants';
-import UserNameGroup from './user_name_group.vue';
+import UserMenuProfileItem from './user_menu_profile_item.vue';
// Left offset required for the dropdown to be aligned with the super sidebar
const DROPDOWN_X_OFFSET_BASE = -211;
@@ -40,7 +40,7 @@ export default {
GlDisclosureDropdownItem,
GlButton,
NewNavToggle,
- UserNameGroup,
+ UserMenuProfileItem,
},
directives: {
SafeHtml,
@@ -247,7 +247,10 @@ export default {
</gl-button>
</template>
- <user-name-group :user="data" />
+ <gl-disclosure-dropdown-group>
+ <user-menu-profile-item :user="data" />
+ </gl-disclosure-dropdown-group>
+
<gl-disclosure-dropdown-group bordered>
<gl-disclosure-dropdown-item
v-if="data.status.can_update"
diff --git a/app/assets/javascripts/super_sidebar/components/user_menu_profile_item.vue b/app/assets/javascripts/super_sidebar/components/user_menu_profile_item.vue
new file mode 100644
index 00000000000..95255ce3d8e
--- /dev/null
+++ b/app/assets/javascripts/super_sidebar/components/user_menu_profile_item.vue
@@ -0,0 +1,83 @@
+<script>
+import { GlBadge, GlDisclosureDropdownItem, GlTooltip } from '@gitlab/ui';
+import SafeHtml from '~/vue_shared/directives/safe_html';
+import { s__ } from '~/locale';
+import { USER_MENU_TRACKING_DEFAULTS } from '../constants';
+
+export default {
+ i18n: {
+ user: {
+ busy: s__('UserProfile|Busy'),
+ },
+ },
+ components: {
+ GlBadge,
+ GlDisclosureDropdownItem,
+ GlTooltip,
+ },
+ directives: {
+ SafeHtml,
+ },
+ props: {
+ user: {
+ required: true,
+ type: Object,
+ },
+ },
+ computed: {
+ menuItem() {
+ const item = {
+ text: this.user.name,
+ };
+ if (this.user.has_link_to_profile) {
+ item.href = this.user.link_to_profile;
+
+ item.extraAttrs = {
+ ...USER_MENU_TRACKING_DEFAULTS,
+ 'data-track-label': 'user_profile',
+ 'data-testid': 'user-profile-link',
+ };
+ }
+
+ return item;
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-disclosure-dropdown-item :item="menuItem">
+ <template #list-item>
+ <span class="gl-display-flex gl-flex-direction-column">
+ <span>
+ <span class="gl-font-weight-bold">
+ {{ user.name }}
+ </span>
+ <gl-badge v-if="user.status.busy" size="sm" variant="warning">
+ {{ $options.i18n.user.busy }}
+ </gl-badge>
+ </span>
+
+ <span class="gl-text-gray-400 gl-word-break-all">@{{ user.username }}</span>
+
+ <span
+ v-if="user.status.customized"
+ ref="statusTooltipTarget"
+ data-testid="user-menu-status"
+ class="gl-display-flex gl-align-items-baseline gl-mt-2 gl-font-sm"
+ >
+ <gl-emoji :data-name="user.status.emoji" class="gl-mr-1" />
+ <span v-safe-html="user.status.message_html" class="gl-text-truncate"></span>
+ <gl-tooltip
+ v-if="user.status.message_html"
+ :target="() => $refs.statusTooltipTarget"
+ boundary="viewport"
+ placement="bottom"
+ >
+ <span v-safe-html="user.status.message_html"></span>
+ </gl-tooltip>
+ </span>
+ </span>
+ </template>
+ </gl-disclosure-dropdown-item>
+</template>
diff --git a/app/assets/javascripts/super_sidebar/components/user_name_group.vue b/app/assets/javascripts/super_sidebar/components/user_name_group.vue
deleted file mode 100644
index 29cc340116b..00000000000
--- a/app/assets/javascripts/super_sidebar/components/user_name_group.vue
+++ /dev/null
@@ -1,91 +0,0 @@
-<script>
-import {
- GlBadge,
- GlDisclosureDropdownGroup,
- GlDisclosureDropdownItem,
- GlTooltip,
-} from '@gitlab/ui';
-import SafeHtml from '~/vue_shared/directives/safe_html';
-import { s__ } from '~/locale';
-import { USER_MENU_TRACKING_DEFAULTS } from '../constants';
-
-export default {
- i18n: {
- user: {
- busy: s__('UserProfile|Busy'),
- },
- },
- components: {
- GlBadge,
- GlDisclosureDropdownGroup,
- GlDisclosureDropdownItem,
- GlTooltip,
- },
- directives: {
- SafeHtml,
- },
- props: {
- user: {
- required: true,
- type: Object,
- },
- },
- computed: {
- menuItem() {
- const item = {
- text: this.user.name,
- };
- if (this.user.has_link_to_profile) {
- item.href = this.user.link_to_profile;
-
- item.extraAttrs = {
- ...USER_MENU_TRACKING_DEFAULTS,
- 'data-track-label': 'user_profile',
- 'data-testid': 'user-profile-link',
- };
- }
-
- return item;
- },
- },
-};
-</script>
-
-<template>
- <gl-disclosure-dropdown-group>
- <gl-disclosure-dropdown-item :item="menuItem">
- <template #list-item>
- <span class="gl-display-flex gl-flex-direction-column">
- <span>
- <span class="gl-font-weight-bold">
- {{ user.name }}
- </span>
- <gl-badge v-if="user.status.busy" size="sm" variant="warning">
- {{ $options.i18n.user.busy }}
- </gl-badge>
- </span>
-
- <span class="gl-text-gray-400 gl-word-break-all">@{{ user.username }}</span>
-
- <span
- v-if="user.status.customized"
- ref="statusTooltipTarget"
- data-testid="user-menu-status"
- class="gl-display-flex gl-align-items-baseline gl-mt-2 gl-font-sm"
- >
- <gl-emoji :data-name="user.status.emoji" class="gl-mr-1" />
- <span v-safe-html="user.status.message_html" class="gl-text-truncate"></span>
- <gl-tooltip
- v-if="user.status.message_html"
- :target="() => $refs.statusTooltipTarget"
- boundary="viewport"
- placement="bottom"
- >
- <span v-safe-html="user.status.message_html"></span>
- </gl-tooltip>
- </span>
- </span>
- </template>
- </gl-disclosure-dropdown-item>
- </gl-disclosure-dropdown-group>
-</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/action_buttons.vue b/app/assets/javascripts/vue_merge_request_widget/components/action_buttons.vue
index c49c1316b1b..619f141144d 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/action_buttons.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/action_buttons.vue
@@ -83,12 +83,6 @@ export default {
return btn.tooltipText;
},
- actionButtonQaSelector(btn) {
- if (btn.dataQaSelector) {
- return btn.dataQaSelector;
- }
- return 'mr_widget_extension_actions_button';
- },
},
};
</script>
@@ -105,7 +99,6 @@ export default {
:target="btn.target"
:class="[{ 'gl-mr-3': index !== tertiaryButtons.length - 1 }, btn.class]"
:data-clipboard-text="btn.dataClipboardText"
- :data-qa-selector="actionButtonQaSelector(btn)"
:data-method="btn.dataMethod"
:icon="btn.icon"
:data-testid="btn.testId || 'extension-actions-button'"
@@ -159,7 +152,6 @@ export default {
:target="btn.target"
:class="[{ 'gl-mr-1': index !== tertiaryButtons.length - 1 }, btn.class]"
:data-clipboard-text="btn.dataClipboardText"
- :data-qa-selector="actionButtonQaSelector(btn)"
:data-method="btn.dataMethod"
:icon="btn.icon"
:data-testid="btn.testId || 'extension-actions-button'"
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue
index 6299f0fcbb8..ec72b74daa2 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue
@@ -75,7 +75,6 @@ export default {
actions.push({
text: this.cancelButtonText,
loading: this.isCancellingAutoMerge,
- dataQaSelector: 'cancel_auto_merge_button',
class: 'js-cancel-auto-merge',
testId: 'cancelAutomaticMergeButton',
onClick: () => this.cancelAutomaticMerge(),
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue
index 4d906f29cb0..4454718a647 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue
@@ -67,7 +67,7 @@ export default {
actions.push({
text: this.revertLabel,
tooltipText: this.revertTitle,
- dataQaSelector: 'revert_button',
+ testId: 'revert-button',
onClick: () => this.openRevertModal(),
});
} else if (this.mr.revertInForkPath) {
@@ -75,7 +75,7 @@ export default {
text: this.revertLabel,
tooltipText: this.revertTitle,
href: this.mr.revertInForkPath,
- dataQaSelector: 'revert_button',
+ testId: 'revert-button',
dataMethod: 'post',
});
}
@@ -84,7 +84,7 @@ export default {
actions.push({
text: this.cherryPickLabel,
tooltipText: this.cherryPickTitle,
- dataQaSelector: 'cherry_pick_button',
+ testId: 'cherry-pick-button',
onClick: () => this.openCherryPickModal(),
});
} else if (this.mr.cherryPickInForkPath) {
@@ -92,7 +92,7 @@ export default {
text: this.cherryPickLabel,
tooltipText: this.cherryPickTitle,
href: this.mr.cherryPickInForkPath,
- dataQaSelector: 'cherry_pick_button',
+ testId: 'cherry-pick-button',
dataMethod: 'post',
});
}
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue
index 415f58ea8e6..a4afdee4d49 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue
@@ -230,7 +230,6 @@ export default {
v-if="!rebasingError"
class="gl-w-100 gl-md-w-auto gl-flex-grow-1 gl-ml-0! gl-text-body! gl-md-mr-3"
data-testid="rebase-message"
- data-qa-selector="no_fast_forward_message_content"
>
<bold-text :message="$options.i18n.rebaseError" />
</span>
@@ -247,7 +246,6 @@ export default {
:loading="isMakingRequest"
variant="confirm"
size="small"
- data-qa-selector="mr_rebase_button"
data-testid="standard-rebase-button"
class="gl-align-self-start"
@click="tryRebase"
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/sha_mismatch.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/sha_mismatch.vue
index 9da754d01fc..00383418f2d 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/sha_mismatch.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/sha_mismatch.vue
@@ -32,7 +32,7 @@ export default {
>
<span
class="gl-md-mr-3 gl-flex-grow-1 gl-ml-0! gl-text-body!"
- data-qa-selector="head_mismatch_content"
+ data-testid="head-mismatch-content"
>
<bold-text :message="$options.i18n.I18N_SHA_MISMATCH.warningMessage" />
</span>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue
index 97ef96fe382..f1bd5bb25bb 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue
@@ -46,7 +46,7 @@ export default {
:disabled="isDisabled"
name="squash"
class="js-squash-checkbox gl-mr-2"
- data-qa-selector="squash_checkbox"
+ data-testid="squash-checkbox"
:title="tooltipTitle"
@change="(checked) => $emit('input', checked)"
>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/widget/action_buttons.vue b/app/assets/javascripts/vue_merge_request_widget/components/widget/action_buttons.vue
index 55eeb9d0e63..5b7657f15d9 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/widget/action_buttons.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/widget/action_buttons.vue
@@ -80,12 +80,6 @@ export default {
return btn.tooltipText;
},
- actionButtonQaSelector(btn) {
- if (btn.dataQaSelector) {
- return btn.dataQaSelector;
- }
- return 'mr_widget_extension_actions_button';
- },
},
};
</script>
@@ -121,7 +115,6 @@ export default {
:target="btn.target"
:class="[{ 'gl-mr-3': index !== tertiaryButtons.length - 1 }, btn.class]"
:data-clipboard-text="btn.dataClipboardText"
- :data-qa-selector="actionButtonQaSelector(btn)"
:data-method="btn.dataMethod"
:icon="btn.icon || btn.iconName"
:data-testid="btn.testId || 'extension-actions-button'"
diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
index 175a0b0563f..b55b59fe581 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
@@ -576,7 +576,7 @@ export default {
</mr-widget-alert-message>
</div>
- <div class="mr-widget-section" data-qa-selector="mr_widget_content">
+ <div class="mr-widget-section" data-testid="mr-widget-content">
<component :is="componentName" :mr="mr" :service="service" />
<ready-to-merge
v-if="mr.commitsCount"
diff --git a/app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue b/app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue
index 05ce007e615..4ebd8861a67 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue
@@ -60,7 +60,7 @@ export default {
<template>
<gl-disclosure-dropdown
- data-qa-selector="apply_suggestion_dropdown"
+ data-testid="apply-suggestion-dropdown"
fluid-width
placement="right"
size="small"
@@ -81,7 +81,7 @@ export default {
class="apply-suggestions-input-min-width"
:placeholder="defaultCommitMessage"
submit-on-enter
- data-qa-selector="commit_message_field"
+ data-testid="commit-message-field"
@submit="onApply"
/>
@@ -93,7 +93,7 @@ export default {
class="gl-w-auto! gl-mt-3 gl-align-self-end"
category="primary"
variant="confirm"
- data-qa-selector="commit_with_custom_message_button"
+ data-testid="commit-with-custom-message-button"
@click="onApply"
>
{{ __('Apply') }}
diff --git a/app/assets/javascripts/vue_shared/components/markdown/header.vue b/app/assets/javascripts/vue_shared/components/markdown/header.vue
index a569b4ea9a7..741bdfd211b 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/header.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/header.vue
@@ -281,7 +281,7 @@ export default {
:tag-content="lineContent"
tracking-property="codeSuggestion"
icon="doc-code"
- data-qa-selector="suggestion_button"
+ data-testid="suggestion-button"
class="js-suggestion-btn"
@click="handleSuggestDismissed"
/>
@@ -305,7 +305,7 @@ export default {
variant="confirm"
category="primary"
size="small"
- data-qa-selector="dismiss_suggestion_popover_button"
+ data-testid="dismiss-suggestion-popover-button"
@click="handleSuggestDismissed"
>
{{ __('Got it') }}
diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue
index 8a0ca8ebac1..a822e2a6151 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue
@@ -144,13 +144,13 @@ export default {
<gl-icon name="question-o" css-classes="link-highlight" />
</a>
</div>
- <gl-badge v-if="isApplied" variant="success" data-qa-selector="applied_badge">
+ <gl-badge v-if="isApplied" variant="success" data-testid="applied-badge">
{{ __('Applied') }}
</gl-badge>
<div
v-else-if="isApplying"
class="gl-display-flex gl-align-items-center text-secondary"
- data-qa-selector="applying_badge"
+ data-testid="applying-badge"
>
<gl-loading-icon size="sm" class="gl-align-items-center gl-justify-content-center gl-mr-3" />
<span>{{ applyingSuggestionsMessage }}</span>
@@ -169,7 +169,7 @@ export default {
<div v-else-if="!isDisableButton && suggestionsCount > 1">
<gl-button
class="btn-inverted js-add-to-batch-btn btn-grouped"
- data-qa-selector="add_suggestion_batch_button"
+ data-testid="add-suggestion-batch-button"
:disabled="isDisableButton"
size="small"
@click="addSuggestionToBatch"
diff --git a/app/models/packages/protection/rule.rb b/app/models/packages/protection/rule.rb
index bb65be92b90..4e8b47f600c 100644
--- a/app/models/packages/protection/rule.rb
+++ b/app/models/packages/protection/rule.rb
@@ -4,18 +4,16 @@ module Packages
module Protection
class Rule < ApplicationRecord
enum package_type: Packages::Package.package_types.slice(:npm)
+ enum push_protected_up_to_access_level:
+ Gitlab::Access.sym_options_with_owner.slice(:developer, :maintainer, :owner),
+ _prefix: :push_protected_up_to
belongs_to :project, inverse_of: :package_protection_rules
validates :package_name_pattern, presence: true, uniqueness: { scope: [:project_id, :package_type] },
length: { maximum: 255 }
validates :package_type, presence: true
- validates :push_protected_up_to_access_level, presence: true,
- inclusion: { in: [
- Gitlab::Access::DEVELOPER,
- Gitlab::Access::MAINTAINER,
- Gitlab::Access::OWNER
- ] }
+ validates :push_protected_up_to_access_level, presence: true
end
end
end
diff --git a/config/feature_flags/development/on_demand_scans_runner_tags.yml b/config/feature_flags/development/prohibited_tag_name_encoding_check.yml
index 6141bae2553..98a51b34cc9 100644
--- a/config/feature_flags/development/on_demand_scans_runner_tags.yml
+++ b/config/feature_flags/development/prohibited_tag_name_encoding_check.yml
@@ -1,8 +1,8 @@
---
-name: on_demand_scans_runner_tags
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/103634
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/381910
-milestone: '15.7'
+name: prohibited_tag_name_encoding_check
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/132135
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/426013
+milestone: '16.5'
type: development
-group: group::dynamic analysis
-default_enabled: true
+group: group::source code
+default_enabled: false
diff --git a/db/migrate/20231010101246_change_push_protected_up_to_access_level_to_smallint_in_packages_protection_rules.rb b/db/migrate/20231010101246_change_push_protected_up_to_access_level_to_smallint_in_packages_protection_rules.rb
new file mode 100644
index 00000000000..d7228b0a3f1
--- /dev/null
+++ b/db/migrate/20231010101246_change_push_protected_up_to_access_level_to_smallint_in_packages_protection_rules.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class ChangePushProtectedUpToAccessLevelToSmallintInPackagesProtectionRules < Gitlab::Database::Migration[2.1]
+ enable_lock_retries!
+
+ def up
+ change_column :packages_protection_rules, :push_protected_up_to_access_level, :integer, limit: 2
+ end
+
+ def down
+ change_column :packages_protection_rules, :push_protected_up_to_access_level, :integer
+ end
+end
diff --git a/db/schema_migrations/20231010101246 b/db/schema_migrations/20231010101246
new file mode 100644
index 00000000000..1b7622c9bc6
--- /dev/null
+++ b/db/schema_migrations/20231010101246
@@ -0,0 +1 @@
+67323d7c15c28b7784bb1021184df4efcc72a38e72e4113a945101c32212a934 \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 324888e9173..3d6800cfc55 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -20196,7 +20196,7 @@ CREATE TABLE packages_protection_rules (
project_id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
- push_protected_up_to_access_level integer NOT NULL,
+ push_protected_up_to_access_level smallint NOT NULL,
package_type smallint NOT NULL,
package_name_pattern text NOT NULL,
CONSTRAINT check_d2d75d206d CHECK ((char_length(package_name_pattern) <= 255))
diff --git a/doc/administration/audit_event_streaming/graphql_api.md b/doc/administration/audit_event_streaming/graphql_api.md
index 768b1f03bf3..905276a8257 100644
--- a/doc/administration/audit_event_streaming/graphql_api.md
+++ b/doc/administration/audit_event_streaming/graphql_api.md
@@ -112,8 +112,19 @@ mutation above.
```graphql
mutation {
- auditEventsStreamingHeadersCreate(input: { destinationId: "gid://gitlab/AuditEvents::ExternalAuditEventDestination/24601", key: "foo", value: "bar" }) {
+ auditEventsStreamingHeadersCreate(input: {
+ destinationId: "gid://gitlab/AuditEvents::ExternalAuditEventDestination/1",
+ key: "foo",
+ value: "bar",
+ active: false
+ }) {
errors
+ header {
+ id
+ key
+ value
+ active
+ }
}
}
```
@@ -146,6 +157,7 @@ query {
key
value
id
+ active
}
}
eventTypeFilters
@@ -500,13 +512,15 @@ mutation {
{
destinationId: "gid://gitlab/AuditEvents::InstanceExternalAuditEventDestination/42",
key: "foo",
- value: "bar"
+ value: "bar",
+ active: true
}) {
errors
header {
id
key
value
+ active
}
}
}
@@ -538,6 +552,7 @@ query {
id
key
value
+ active
}
}
eventTypeFilters
@@ -590,12 +605,13 @@ by [listing all the custom HTTP headers](#list-streaming-destinations-1) for the
```graphql
mutation {
- auditEventsStreamingInstanceHeadersUpdate(input: { headerId: "gid://gitlab/AuditEvents::Streaming::InstanceHeader/2", key: "new-key", value: "new-value" }) {
+ auditEventsStreamingInstanceHeadersUpdate(input: { headerId: "gid://gitlab/AuditEvents::Streaming::InstanceHeader/2", key: "new-key", value: "new-value", active: false }) {
errors
header {
id
key
value
+ active
}
}
}
diff --git a/doc/user/application_security/dast/proxy-based.md b/doc/user/application_security/dast/proxy-based.md
index 86af7d4c5da..230d8ef5ca3 100644
--- a/doc/user/application_security/dast/proxy-based.md
+++ b/doc/user/application_security/dast/proxy-based.md
@@ -464,7 +464,6 @@ The DAST job does not require the project's repository to be present when runnin
> - Auditing for DAST profile management [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217872) in GitLab 14.1.
> - Scheduled on-demand DAST scans [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/328749) in GitLab 14.3 [with a flag](../../../administration/feature_flags.md) named `dast_on_demand_scans_scheduler`. Disabled by default.
> - Scheduled on-demand DAST scans [generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/328749) in GitLab 14.5. Feature flag `dast_on_demand_scans_scheduler` removed.
-> - Runner tags selection [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345430) in GitLab 15.9 [with a flag](../../../administration/feature_flags.md) named `on_demand_scans_runner_tags. Disabled by default.
> - Runner tags selection [enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/111499) in GitLab 16.3.
WARNING:
diff --git a/doc/user/project/repository/managing_large_repositories.md b/doc/user/project/repository/managing_large_repositories.md
index 83ba0da9865..721150f958b 100644
--- a/doc/user/project/repository/managing_large_repositories.md
+++ b/doc/user/project/repository/managing_large_repositories.md
@@ -263,12 +263,46 @@ following sections for information on solving:
### Large number of references
-A reference in Git (a branch or tag) is used to refer to a commit. If you are
-curious, you can go to any `.git` directory and look under the `refs` directory.
-
-A large number of references can cause performance problems because, with more
-references, object walks that Git does are larger for various operations such as
-clones, pushes, and housekeeping tasks.
+[References in Git](https://git-scm.com/book/en/v2/Git-Internals-Git-References)
+are branch and tag names that point to a particular commit. You can use the `git
+for-each-ref` command to list all references present in a repository. A large
+number of references in a repository can have detrimental impact on the command's
+performance. To understand why, we need to understand how Git stores references
+and uses them.
+
+In general, Git stores all references as loose files in the `.git/refs` folder of
+the repository. As the number of references grows, the seek time to find a
+particular reference in the folder also increases. Therefore, every time Git has
+to parse a reference, there is an increased latency due to the added seek time
+of the file system.
+
+To resolve this issue, Git uses [pack-refs](https://git-scm.com/docs/git-pack-refs). In short, instead of storing each
+reference in a single file, Git creates a single `.git/packed-refs` file that
+contains all the references for that repository. This file reduces storage space
+while also increasing performance because seeking within a single file is faster
+than seeking a file within a directory. However, creating and updating new references
+is still done through loose files and are not added to the `packed-refs` file. To
+recreate the `packed-refs` file, run `git pack-refs`.
+
+Gitaly runs `git pack-refs` during [housekeeping](../../../administration/housekeeping.md#heuristical-housekeeping)
+to move loose references into `packed-refs` files. While this is very beneficial
+for most repositories, write-heavy repositories still have the problem that:
+
+- Creating or updating references creates new loose files.
+- Deleting references involves modifying the existing `packed-refs` file
+ altogether to remove the existing reference.
+
+These problems still cause the same performance issues.
+
+In addition, fetches and clones from repositories includes the transfer
+of missing objects from the server to the client. When there are numerous
+references, Git iterates over all references and walks the internal graph
+structure for each reference to find the missing objects to transfer to
+the client. Iteration and walking are CPU-intensive operations that increase
+the latency of these commands.
+
+In repositories with a lot of activity, this often causes a domino effect because
+every operation is slower and each operation stalls subsequent operations.
#### Mitigation strategies
diff --git a/lib/api/entities/bulk_import.rb b/lib/api/entities/bulk_import.rb
index 75989cb4180..18f71048595 100644
--- a/lib/api/entities/bulk_import.rb
+++ b/lib/api/entities/bulk_import.rb
@@ -10,6 +10,7 @@ module API
expose :source_type, documentation: { type: 'string', example: 'gitlab' }
expose :created_at, documentation: { type: 'dateTime', example: '2012-05-28T04:42:42-07:00' }
expose :updated_at, documentation: { type: 'dateTime', example: '2012-05-28T04:42:42-07:00' }
+ expose :has_failures, documentation: { type: 'boolean', example: false }
end
end
end
diff --git a/lib/api/entities/bulk_imports/entity.rb b/lib/api/entities/bulk_imports/entity.rb
index 176d10b2580..7e9b9973e15 100644
--- a/lib/api/entities/bulk_imports/entity.rb
+++ b/lib/api/entities/bulk_imports/entity.rb
@@ -24,6 +24,7 @@ module API
expose :updated_at, documentation: { type: 'dateTime', example: '2012-05-28T04:42:42-07:00' }
expose :failures, using: EntityFailure, documentation: { is_array: true }
expose :migrate_projects, documentation: { type: 'boolean', example: true }
+ expose :has_failures, documentation: { type: 'boolean', example: false }
end
end
end
diff --git a/lib/gitlab/checks/tag_check.rb b/lib/gitlab/checks/tag_check.rb
index 4505bcb5411..d5addab74b8 100644
--- a/lib/gitlab/checks/tag_check.rb
+++ b/lib/gitlab/checks/tag_check.rb
@@ -11,7 +11,8 @@ module Gitlab
delete_protected_tag_non_web: 'You can only delete protected tags using the web interface.',
create_protected_tag: 'You are not allowed to create this tag as it is protected.',
default_branch_collision: 'You cannot use default branch name to create a tag',
- prohibited_tag_name: 'You cannot create a tag with a prohibited pattern.'
+ prohibited_tag_name: 'You cannot create a tag with a prohibited pattern.',
+ prohibited_tag_name_encoding: 'Tag names must be valid when converted to UTF-8 encoding'
}.freeze
LOG_MESSAGES = {
@@ -46,6 +47,16 @@ module Gitlab
if tag_name.start_with?("refs/tags/") # rubocop: disable Style/GuardClause
raise GitAccess::ForbiddenError, ERROR_MESSAGES[:prohibited_tag_name]
end
+
+ # rubocop: disable Style/GuardClause
+ # rubocop: disable Style/SoleNestedConditional
+ if Feature.enabled?(:prohibited_tag_name_encoding_check, project)
+ unless Gitlab::EncodingHelper.force_encode_utf8(tag_name).valid_encoding?
+ raise GitAccess::ForbiddenError, ERROR_MESSAGES[:prohibited_tag_name_encoding]
+ end
+ end
+ # rubocop: enable Style/SoleNestedConditional
+ # rubocop: enable Style/GuardClause
end
def protected_tag_checks
diff --git a/lib/gitlab/encoding_helper.rb b/lib/gitlab/encoding_helper.rb
index 99240f2ad48..b080cb197d4 100644
--- a/lib/gitlab/encoding_helper.rb
+++ b/lib/gitlab/encoding_helper.rb
@@ -152,8 +152,6 @@ module Gitlab
message.delete_prefix(BOM_UTF8)
end
- private
-
def force_encode_utf8(message)
raise ArgumentError unless message.respond_to?(:force_encoding)
return message if message.encoding == Encoding::UTF_8 && message.valid_encoding?
@@ -163,6 +161,8 @@ module Gitlab
message.force_encoding("UTF-8")
end
+ private
+
# Escapes \x80 - \xFF characters not supported by UTF-8
def escape_chars(char)
bytes = char.bytes
diff --git a/qa/qa/page/main/menu.rb b/qa/qa/page/main/menu.rb
index 98d00664854..2413166e120 100644
--- a/qa/qa/page/main/menu.rb
+++ b/qa/qa/page/main/menu.rb
@@ -21,7 +21,7 @@ module QA
element :edit_profile_link
end
- view 'app/assets/javascripts/super_sidebar/components/user_name_group.vue' do
+ view 'app/assets/javascripts/super_sidebar/components/user_menu_profile_item.vue' do
element 'user-profile-link'
end
diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb
index 3782ae0c9d0..a51c65a18c6 100644
--- a/qa/qa/page/merge_request/show.rb
+++ b/qa/qa/page/merge_request/show.rb
@@ -71,13 +71,13 @@ module QA
end
view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue' do
- element :cherry_pick_button
- element :revert_button
+ element 'cherry-pick-button'
+ element 'revert-button'
end
view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue' do
- element :mr_rebase_button
- element :no_fast_forward_message_content
+ element 'standard-rebase-button'
+ element 'rebase-message'
end
view 'app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue' do
@@ -88,33 +88,33 @@ module QA
end
view 'app/assets/javascripts/vue_merge_request_widget/components/states/sha_mismatch.vue' do
- element :head_mismatch_content
+ element 'head-mismatch-content'
end
view 'app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue' do
- element :squash_checkbox
+ element 'squash-checkbox'
end
view 'app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue' do
- element :mr_widget_content
+ element 'mr-widget-content'
element 'pipeline-container'
end
view 'app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue' do
- element :apply_suggestion_dropdown
- element :commit_message_field
- element :commit_with_custom_message_button
+ element 'apply-suggestion-dropdown'
+ element 'commit-message-field'
+ element 'commit-with-custom-message-button'
end
view 'app/assets/javascripts/vue_shared/components/markdown/header.vue' do
- element :suggestion_button
- element :dismiss_suggestion_popover_button
+ element 'suggestion-button'
+ element 'dismiss-suggestion-popover-button'
end
view 'app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue' do
- element :add_suggestion_batch_button
- element :applied_badge
- element :applying_badge
+ element 'add-suggestion-batch-button'
+ element 'applied-badge'
+ element 'applying-badge'
end
view 'app/views/projects/merge_requests/_description.html.haml' do
@@ -132,10 +132,6 @@ module QA
element 'diffs-tab', required: true
end
- view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue' do
- element :cancel_auto_merge_button
- end
-
view 'app/views/shared/_broadcast_message.html.haml' do
element 'broadcast-notification-container'
element 'close-button'
@@ -195,7 +191,9 @@ module QA
all_elements('left-line-number', minimum: 1).first.hover
click_element('left-comment-button')
- click_element(:dismiss_suggestion_popover_button) if has_element?(:dismiss_suggestion_popover_button, wait: 1)
+
+ click_element('dismiss-suggestion-popover-button') if has_element?('dismiss-suggestion-popover-button',
+ wait: 1)
fill_element('reply-field', text)
end
@@ -227,7 +225,7 @@ module QA
end
def fast_forward_not_possible?
- has_element?(:no_fast_forward_message_content)
+ has_element?('rebase-message')
end
def has_file?(file_name)
@@ -290,15 +288,15 @@ module QA
def mark_to_squash
# Refresh page if commit arrived after loading the MR page
wait_until(reload: true, message: 'Wait for MR to be unblocked') do
- has_no_element?(:head_mismatch_content, wait: 1)
+ has_no_element?('head-mismatch-content', wait: 1)
end
# The squash checkbox is enabled via JS
wait_until(reload: false) do
- !find_element(:squash_checkbox, visible: false).disabled?
+ !find_element('squash-checkbox', visible: false).disabled?
end
- check_element(:squash_checkbox, true)
+ check_element('squash-checkbox', true)
end
def merge!
@@ -338,7 +336,7 @@ module QA
# Waits up 10 seconds and returns false if the Revert button is not enabled
def revertible?
- has_element?(:revert_button, disabled: false, wait: 10)
+ has_element?('revert-button', disabled: false, wait: 10)
end
# Waits up 60 seconds and raises an error if unable to merge.
@@ -357,7 +355,7 @@ module QA
break true unless find_element('merge-button').disabled?
# If the widget shows "Merge blocked: new changes were just added" we can refresh the page and check again
- next false if has_element?(:head_mismatch_content, wait: 1)
+ next false if has_element?('head-mismatch-content', wait: 1)
# Stop waiting if we're in a transient test. By this point we're in an unexpected state and should let the
# test fail so we can investigate. If we're not in a transient test we keep trying until we reach timeout.
@@ -372,15 +370,15 @@ module QA
def rebase!
# The rebase button is disabled on load
wait_until do
- has_element?(:mr_rebase_button)
+ has_element?('standard-rebase-button')
end
# The rebase button is enabled via JS
wait_until(reload: false) do
- !find_element(:mr_rebase_button).disabled?
+ !find_element('standard-rebase-button').disabled?
end
- click_element(:mr_rebase_button)
+ click_element('standard-rebase-button')
end
def merge_immediately!
@@ -448,7 +446,7 @@ module QA
def add_suggestion_to_diff(suggestion, line)
find("a[data-linenumber='#{line}']").hover
click_element('left-comment-button')
- click_element(:suggestion_button)
+ click_element('suggestion-button')
initial_content = find_element('reply-field').value
fill_element('reply-field', '')
fill_element('reply-field', initial_content.gsub(/(```suggestion:-0\+0\n).*(\n```)/, "\\1#{suggestion}\\2"))
@@ -457,24 +455,24 @@ module QA
end
def apply_suggestion_with_message(message)
- all_elements(:apply_suggestion_dropdown, minimum: 1).first.click
- fill_element(:commit_message_field, message)
- click_element(:commit_with_custom_message_button)
+ all_elements('apply-suggestion-dropdown', minimum: 1).first.click
+ fill_element('commit-message-field', message)
+ click_element('commit-with-custom-message-button')
end
def add_suggestion_to_batch
- all_elements(:add_suggestion_batch_button, minimum: 1).first.click
+ all_elements('add-suggestion-batch-button', minimum: 1).first.click
end
def has_suggestions_applied?(count = 1)
wait_until(reload: false) do
- has_no_element?(:applying_badge)
+ has_no_element?('applying-badge')
end
- all_elements(:applied_badge, count: count)
+ all_elements('applied-badge', count: count)
end
def cherry_pick!
- click_element(:cherry_pick_button, Page::Component::CommitModal)
+ click_element('cherry-pick-button', Page::Component::CommitModal)
click_element(:submit_commit_button)
end
@@ -482,13 +480,13 @@ module QA
# reload page when the revert modal occasionally doesn't appear in ee:large-setup job
# https://gitlab.com/gitlab-org/gitlab/-/issues/386623 (transient issue)
retry_on_exception(reload: true) do
- click_element(:revert_button, Page::Component::CommitModal)
+ click_element('revert-button', Page::Component::CommitModal)
end
click_element(:submit_commit_button)
end
def mr_widget_text
- find_element(:mr_widget_content).text
+ find_element('mr-widget-content').text
end
def has_fork_icon?
diff --git a/qa/qa/specs/features/browser_ui/4_verify/ci_project_artifacts/user_can_bulk_delete_artifacts_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/ci_project_artifacts/user_can_bulk_delete_artifacts_spec.rb
index 17c83a32d52..27969759adf 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/ci_project_artifacts/user_can_bulk_delete_artifacts_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/ci_project_artifacts/user_can_bulk_delete_artifacts_spec.rb
@@ -23,7 +23,7 @@ module QA
after do
Parallel.each((0..(total_runners_count - 1)), in_threads: 3) do |i|
- runners[i].remove_via_api!
+ runners[i]&.remove_via_api!
end
end
@@ -46,7 +46,7 @@ module QA
def launch_runners
Parallel.each((1..total_runners_count), in_threads: 3) do |i|
- runners << create(:project_runner, project: project, name: "executor-#{i}", tags: [executor])
+ runners << create(:project_runner, project: project, name: "#{executor}-#{i}", tags: [executor])
end
end
diff --git a/spec/factories/packages/protection/rules.rb b/spec/factories/packages/protection/rules.rb
index 3038fb847e7..f65a9d3e64d 100644
--- a/spec/factories/packages/protection/rules.rb
+++ b/spec/factories/packages/protection/rules.rb
@@ -5,6 +5,6 @@ FactoryBot.define do
project
package_name_pattern { '@my_scope/my_package' }
package_type { :npm }
- push_protected_up_to_access_level { Gitlab::Access::DEVELOPER }
+ push_protected_up_to_access_level { :developer }
end
end
diff --git a/spec/frontend/design_management/pages/index_spec.js b/spec/frontend/design_management/pages/index_spec.js
index 961ea27f0f4..9b5e812c021 100644
--- a/spec/frontend/design_management/pages/index_spec.js
+++ b/spec/frontend/design_management/pages/index_spec.js
@@ -191,7 +191,7 @@ describe('Design management index page', () => {
[moveDesignMutation, moveDesignHandler],
];
- fakeApollo = createMockApollo(requestHandlers, {}, { addTypename: true });
+ fakeApollo = createMockApollo(requestHandlers, {});
wrapper = shallowMountExtended(Index, {
apolloProvider: fakeApollo,
router,
diff --git a/spec/frontend/super_sidebar/components/user_name_group_spec.js b/spec/frontend/super_sidebar/components/user_menu_profile_item_spec.js
index a31ad93d143..9cf55154a59 100644
--- a/spec/frontend/super_sidebar/components/user_name_group_spec.js
+++ b/spec/frontend/super_sidebar/components/user_menu_profile_item_spec.js
@@ -1,12 +1,11 @@
-import { GlDisclosureDropdownGroup, GlDisclosureDropdownItem, GlTooltip } from '@gitlab/ui';
+import { GlDisclosureDropdownItem, GlTooltip } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import UserNameGroup from '~/super_sidebar/components/user_name_group.vue';
+import UserMenuProfileItem from '~/super_sidebar/components/user_menu_profile_item.vue';
import { userMenuMockData, userMenuMockStatus } from '../mock_data';
-describe('UserNameGroup component', () => {
+describe('UserMenuProfileItem component', () => {
let wrapper;
- const findGlDisclosureDropdownGroup = () => wrapper.findComponent(GlDisclosureDropdownGroup);
const findGlDisclosureDropdownItem = () => wrapper.findComponent(GlDisclosureDropdownItem);
const findGlTooltip = () => wrapper.findComponent(GlTooltip);
const findUserStatus = () => wrapper.findByTestId('user-menu-status');
@@ -14,7 +13,7 @@ describe('UserNameGroup component', () => {
const GlEmoji = { template: '<img/>' };
const createWrapper = (userDataChanges = {}) => {
- wrapper = shallowMountExtended(UserNameGroup, {
+ wrapper = shallowMountExtended(UserMenuProfileItem, {
propsData: {
user: {
...userMenuMockData,
@@ -32,10 +31,6 @@ describe('UserNameGroup component', () => {
createWrapper();
});
- it('renders the menu item in a separate group', () => {
- expect(findGlDisclosureDropdownGroup().exists()).toBe(true);
- });
-
it('renders menu item', () => {
expect(findGlDisclosureDropdownItem().exists()).toBe(true);
});
diff --git a/spec/frontend/super_sidebar/components/user_menu_spec.js b/spec/frontend/super_sidebar/components/user_menu_spec.js
index d41a414f69e..79a31492f3f 100644
--- a/spec/frontend/super_sidebar/components/user_menu_spec.js
+++ b/spec/frontend/super_sidebar/components/user_menu_spec.js
@@ -2,7 +2,7 @@ import { GlAvatar, GlDisclosureDropdown } from '@gitlab/ui';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import { stubComponent } from 'helpers/stub_component';
import UserMenu from '~/super_sidebar/components/user_menu.vue';
-import UserNameGroup from '~/super_sidebar/components/user_name_group.vue';
+import UserMenuProfileItem from '~/super_sidebar/components/user_menu_profile_item.vue';
import NewNavToggle from '~/nav/components/new_nav_toggle.vue';
import invalidUrl from '~/lib/utils/invalid_url';
import { mockTracking } from 'helpers/tracking_helper';
@@ -86,9 +86,9 @@ describe('UserMenu component', () => {
describe('User Menu Group', () => {
it('renders and passes data to it', () => {
createWrapper();
- const userNameGroup = wrapper.findComponent(UserNameGroup);
- expect(userNameGroup.exists()).toBe(true);
- expect(userNameGroup.props('user')).toEqual(userMenuMockData);
+ const userMenuProfileItem = wrapper.findComponent(UserMenuProfileItem);
+ expect(userMenuProfileItem.exists()).toBe(true);
+ expect(userMenuProfileItem.props('user')).toEqual(userMenuMockData);
});
});
diff --git a/spec/frontend/work_items/components/work_item_links/work_item_links_spec.js b/spec/frontend/work_items/components/work_item_links/work_item_links_spec.js
index 111fb5d8458..0b88b3ff5b4 100644
--- a/spec/frontend/work_items/components/work_item_links/work_item_links_spec.js
+++ b/spec/frontend/work_items/components/work_item_links/work_item_links_spec.js
@@ -54,7 +54,6 @@ describe('WorkItemLinks', () => {
[issueDetailsQuery, issueDetailsQueryHandler],
],
resolvers,
- { addTypename: true },
);
wrapper = shallowMountExtended(WorkItemLinks, {
diff --git a/spec/lib/api/entities/bulk_import_spec.rb b/spec/lib/api/entities/bulk_import_spec.rb
index 2db6862b079..cfa293463ad 100644
--- a/spec/lib/api/entities/bulk_import_spec.rb
+++ b/spec/lib/api/entities/bulk_import_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe API::Entities::BulkImport do
+RSpec.describe API::Entities::BulkImport, feature_category: :importers do
let_it_be(:import) { create(:bulk_import) }
subject { described_class.new(import).as_json }
@@ -13,7 +13,8 @@ RSpec.describe API::Entities::BulkImport do
:status,
:source_type,
:created_at,
- :updated_at
+ :updated_at,
+ :has_failures
)
end
end
diff --git a/spec/lib/api/entities/bulk_imports/entity_spec.rb b/spec/lib/api/entities/bulk_imports/entity_spec.rb
index ba8a2ddffcb..791cd3a20e2 100644
--- a/spec/lib/api/entities/bulk_imports/entity_spec.rb
+++ b/spec/lib/api/entities/bulk_imports/entity_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe API::Entities::BulkImports::Entity do
+RSpec.describe API::Entities::BulkImports::Entity, feature_category: :importers do
let_it_be(:entity) { create(:bulk_import_entity) }
subject { described_class.new(entity).as_json }
@@ -22,7 +22,8 @@ RSpec.describe API::Entities::BulkImports::Entity do
:created_at,
:updated_at,
:failures,
- :migrate_projects
+ :migrate_projects,
+ :has_failures
)
end
end
diff --git a/spec/lib/gitlab/checks/tag_check_spec.rb b/spec/lib/gitlab/checks/tag_check_spec.rb
index 60d3eb4bfb3..b5aafde006f 100644
--- a/spec/lib/gitlab/checks/tag_check_spec.rb
+++ b/spec/lib/gitlab/checks/tag_check_spec.rb
@@ -41,6 +41,36 @@ RSpec.describe Gitlab::Checks::TagCheck, feature_category: :source_code_manageme
expect { subject.validate! }.not_to raise_error
end
end
+
+ it "prohibits tag names that include characters incompatible with UTF-8" do
+ allow(subject).to receive(:tag_name).and_return("v6.0.0-\xCE.BETA")
+
+ expect { subject.validate! }.to raise_error(Gitlab::GitAccess::ForbiddenError, "Tag names must be valid when converted to UTF-8 encoding")
+ end
+
+ it "doesn't prohibit UTF-8 compatible characters" do
+ allow(subject).to receive(:tag_name).and_return("v6.0.0-Ü.BETA")
+
+ expect { subject.validate! }.not_to raise_error
+ end
+
+ context "when prohibited_tag_name_encoding_check feature flag is disabled" do
+ before do
+ stub_feature_flags(prohibited_tag_name_encoding_check: false)
+ end
+
+ it "doesn't prohibit tag names that include characters incompatible with UTF-8" do
+ allow(subject).to receive(:tag_name).and_return("v6.0.0-\xCE.BETA")
+
+ expect { subject.validate! }.not_to raise_error
+ end
+
+ it "doesn't prohibit UTF-8 compatible characters" do
+ allow(subject).to receive(:tag_name).and_return("v6.0.0-Ü.BETA")
+
+ expect { subject.validate! }.not_to raise_error
+ end
+ end
end
context 'with protected tag' do
diff --git a/spec/lib/gitlab/encoding_helper_spec.rb b/spec/lib/gitlab/encoding_helper_spec.rb
index bc72d1a67d6..1b7c11dfef6 100644
--- a/spec/lib/gitlab/encoding_helper_spec.rb
+++ b/spec/lib/gitlab/encoding_helper_spec.rb
@@ -2,7 +2,7 @@
require "spec_helper"
-RSpec.describe Gitlab::EncodingHelper do
+RSpec.describe Gitlab::EncodingHelper, feature_category: :shared do
using RSpec::Parameterized::TableSyntax
let(:ext_class) { Class.new { extend Gitlab::EncodingHelper } }
@@ -291,4 +291,39 @@ RSpec.describe Gitlab::EncodingHelper do
expect(described_class.strip_bom("BOM at the end\xEF\xBB\xBF")).to eq("BOM at the end\xEF\xBB\xBF")
end
end
+
+ # This cop's alternative to .dup doesn't work in this context for some reason.
+ # rubocop: disable Performance/UnfreezeString
+ describe "#force_encode_utf8" do
+ let(:stringish) do
+ Class.new(String) do
+ undef :force_encoding
+ end
+ end
+
+ it "raises an ArgumentError if the argument can't force encoding" do
+ expect { described_class.force_encode_utf8(stringish.new("foo")) }.to raise_error(ArgumentError)
+ end
+
+ it "returns the message if already UTF-8 and valid encoding" do
+ string = "føø".dup
+
+ expect(string).not_to receive(:force_encoding).and_call_original
+ expect(described_class.force_encode_utf8(string)).to eq("føø")
+ end
+
+ it "forcibly encodes a string to UTF-8" do
+ string = "føø".dup.force_encoding("ISO-8859-1")
+
+ expect(string).to receive(:force_encoding).with("UTF-8").and_call_original
+ expect(described_class.force_encode_utf8(string)).to eq("føø")
+ end
+
+ it "forcibly encodes a frozen string to UTF-8" do
+ string = "bår".dup.force_encoding("ISO-8859-1").freeze
+
+ expect(described_class.force_encode_utf8(string)).to eq("bår")
+ end
+ end
+ # rubocop: enable Performance/UnfreezeString
end
diff --git a/spec/models/packages/protection/rule_spec.rb b/spec/models/packages/protection/rule_spec.rb
index b368687e6d8..d59c374b442 100644
--- a/spec/models/packages/protection/rule_spec.rb
+++ b/spec/models/packages/protection/rule_spec.rb
@@ -10,9 +10,19 @@ RSpec.describe Packages::Protection::Rule, type: :model, feature_category: :pack
end
describe 'enums' do
- describe '#package_type' do
- it { is_expected.to define_enum_for(:package_type).with_values(npm: Packages::Package.package_types[:npm]) }
- end
+ it { is_expected.to define_enum_for(:package_type).with_values(npm: Packages::Package.package_types[:npm]) }
+
+ it {
+ is_expected.to(
+ define_enum_for(:push_protected_up_to_access_level)
+ .with_values(
+ developer: Gitlab::Access::DEVELOPER,
+ maintainer: Gitlab::Access::MAINTAINER,
+ owner: Gitlab::Access::OWNER
+ )
+ .with_prefix(:push_protected_up_to)
+ )
+ }
end
describe 'validations' do
@@ -30,11 +40,6 @@ RSpec.describe Packages::Protection::Rule, type: :model, feature_category: :pack
describe '#push_protected_up_to_access_level' do
it { is_expected.to validate_presence_of(:push_protected_up_to_access_level) }
-
- it {
- is_expected.to validate_inclusion_of(:push_protected_up_to_access_level).in_array([Gitlab::Access::DEVELOPER,
- Gitlab::Access::MAINTAINER, Gitlab::Access::OWNER])
- }
end
end
end