diff --git a/app/assets/javascripts/admin/abuse_reports/constants.js b/app/assets/javascripts/admin/abuse_reports/constants.js index 297dc2df6da..62522f0eb0c 100644 --- a/app/assets/javascripts/admin/abuse_reports/constants.js +++ b/app/assets/javascripts/admin/abuse_reports/constants.js @@ -25,7 +25,7 @@ export const FILTERED_SEARCH_TOKEN_USER = { export const FILTERED_SEARCH_TOKEN_REPORTER = { ...FILTERED_SEARCH_TOKEN_USER, type: 'reporter', - title: __('Reporter'), + title: s__('AbuseReport|Reporter'), }; export const FILTERED_SEARCH_TOKEN_STATUS = { diff --git a/app/assets/javascripts/graphql_shared/issuable_client.js b/app/assets/javascripts/graphql_shared/issuable_client.js index 5a77c1f4b0a..b119639b249 100644 --- a/app/assets/javascripts/graphql_shared/issuable_client.js +++ b/app/assets/javascripts/graphql_shared/issuable_client.js @@ -80,6 +80,11 @@ export const config = { }, }, }, + Namespace: { + fields: { + merge: true, + }, + }, WorkItemWidgetNotes: { fields: { // If we add any key args, the discussions field becomes discussions({"filter":"ONLY_ACTIVITY","first":10}) and diff --git a/app/assets/javascripts/issuable/components/related_issuable_item.vue b/app/assets/javascripts/issuable/components/related_issuable_item.vue index 5a2af4dae5a..a94d08e4cef 100644 --- a/app/assets/javascripts/issuable/components/related_issuable_item.vue +++ b/app/assets/javascripts/issuable/components/related_issuable_item.vue @@ -196,7 +196,7 @@ export default { - + diff --git a/app/assets/javascripts/work_items/components/design_management/design_management_widget.vue b/app/assets/javascripts/work_items/components/design_management/design_management_widget.vue index cc11edd7fd5..e503491f984 100644 --- a/app/assets/javascripts/work_items/components/design_management/design_management_widget.vue +++ b/app/assets/javascripts/work_items/components/design_management/design_management_widget.vue @@ -69,6 +69,11 @@ export default { required: false, default: ALERT_VARIANTS.danger, }, + canReorderDesign: { + type: Boolean, + required: false, + default: false, + }, }, apollo: { designCollection: { @@ -155,6 +160,7 @@ export default { return ( !this.$options.isLoggedIn || !this.isLatestVersion || + !this.canReorderDesign || this.isReorderingInProgress || this.isMobile ); @@ -332,6 +338,10 @@ export default { dragOptions: { animation: 200, ghostClass: 'gl-invisible', + forceFallback: true, + tag: 'ol', + filter: '.no-drag', + draggable: '.js-design-tile', }, i18n: { designLoadingError: s__( @@ -441,10 +451,6 @@ export default { :value="designs" :disabled="isDraggingDisabled" v-bind="$options.dragOptions" - :force-fallback="true" - tag="ol" - draggable=".js-design-tile" - filter=".no-drag" class="list-unstyled row -gl-my-1 gl-flex gl-gap-y-5" :class="{ 'gl-px-3 gl-py-2': hasDesigns, 'gl-hidden': !hasDesigns }" @end="onDragEnd" diff --git a/app/assets/javascripts/work_items/components/work_item_actions.vue b/app/assets/javascripts/work_items/components/work_item_actions.vue index bb5f032e6bf..d21c84cea26 100644 --- a/app/assets/javascripts/work_items/components/work_item_actions.vue +++ b/app/assets/javascripts/work_items/components/work_item_actions.vue @@ -18,6 +18,7 @@ import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import toast from '~/vue_shared/plugins/global_toast'; import { isLoggedIn } from '~/lib/utils/common_utils'; +import WorkItemChangeTypeModal from 'ee_else_ce/work_items/components/work_item_change_type_modal.vue'; import { sprintfWorkItem, BASE_ALLOWED_CREATE_TYPES, @@ -50,7 +51,6 @@ import updateWorkItemMutation from '../graphql/update_work_item.mutation.graphql import updateWorkItemNotificationsMutation from '../graphql/update_work_item_notifications.mutation.graphql'; import convertWorkItemMutation from '../graphql/work_item_convert.mutation.graphql'; import namespaceWorkItemTypesQuery from '../graphql/namespace_work_item_types.query.graphql'; -import WorkItemChangeTypeModal from './work_item_change_type_modal.vue'; import WorkItemStateToggle from './work_item_state_toggle.vue'; import CreateWorkItemModal from './create_work_item_modal.vue'; @@ -227,6 +227,11 @@ export default { required: false, default: () => [], }, + namespaceFullName: { + type: String, + required: false, + default: '', + }, }, data() { return { @@ -326,7 +331,7 @@ export default { : this.$options.i18n.confidentialityEnabled; }, showChangeType() { - return !this.isEpic && this.glFeatures.workItemsBeta; + return !this.isEpic && this.glFeatures.workItemsBeta && this.$options.isLoggedIn; }, allowedWorkItemTypes() { if (this.isGroup) { @@ -644,13 +649,16 @@ export default { v-if="showChangeType" ref="workItemsChangeTypeModal" :work-item-id="workItemId" + :work-item-iid="workItemIid" :work-item-type="workItemType" :full-path="fullPath" :has-children="hasChildren" :has-parent="hasParent" :widgets="widgets" :allowed-child-types="allowedChildTypes" + :namespace-full-name="namespaceFullName" @workItemTypeChanged="$emit('workItemTypeChanged')" + @error="$emit('error', $event)" /> diff --git a/app/assets/javascripts/work_items/components/work_item_change_type_modal.vue b/app/assets/javascripts/work_items/components/work_item_change_type_modal.vue index 9a9cdcd9bf1..531f79ee9d8 100644 --- a/app/assets/javascripts/work_items/components/work_item_change_type_modal.vue +++ b/app/assets/javascripts/work_items/components/work_item_change_type_modal.vue @@ -13,6 +13,8 @@ import { WORK_ITEM_ALLOWED_CHANGE_TYPE_MAP, WORK_ITEM_TYPE_ENUM_OBJECTIVE, WORK_ITEM_TYPE_ENUM_KEY_RESULT, + WORK_ITEM_TYPE_ENUM_EPIC, + WORK_ITEM_TYPE_VALUE_EPIC, sprintfWorkItem, I18N_WORK_ITEM_CHANGE_TYPE_PARENT_ERROR, I18N_WORK_ITEM_CHANGE_TYPE_CHILD_ERROR, @@ -42,6 +44,11 @@ export default { type: String, required: true, }, + workItemIid: { + type: String, + required: false, + default: '', + }, workItemType: { type: String, required: false, @@ -71,15 +78,36 @@ export default { required: false, default: () => [], }, + namespaceFullName: { + type: String, + required: false, + default: '', + }, + allowedWorkItemTypesEE: { + type: Array, + required: false, + default: () => [], + }, + epicFieldNote: { + type: String, + required: false, + default: '', + }, + getEpicWidgetDefinitions: { + type: Function, + required: false, + default: () => () => {}, + }, }, data() { return { selectedWorkItemType: null, workItemTypes: [], warningMessage: '', - errorMessage: '', changeTypeDisabled: true, hasDesigns: false, + workItemFullPath: this.fullPath, + typeFieldNote: '', }; }, apollo: { @@ -87,14 +115,19 @@ export default { query: namespaceWorkItemTypesQuery, variables() { return { - fullPath: this.fullPath, + fullPath: this.workItemFullPath, }; }, update(data) { return data.workspace?.workItemTypes?.nodes; }, error(e) { - this.showErrorMessage(e); + this.throwError(e); + }, + result() { + if (this.selectedWorkItemType !== null) { + this.validateWorkItemType(); + } }, }, hasDesigns: { @@ -112,7 +145,7 @@ export default { return !this.workItemId; }, error(e) { - this.showErrorMessage(e); + this.throwError(e); }, }, }, @@ -120,7 +153,7 @@ export default { allowedConversionWorkItemTypes() { // The logic will be simplified once we implement // https://gitlab.com/gitlab-org/gitlab/-/issues/498656 - return [ + let allowedWorkItemTypes = [ { text: __('Select type'), value: null }, ...Object.entries(WORK_ITEMS_TYPE_MAP) .map(([key, value]) => ({ @@ -141,12 +174,21 @@ export default { return WORK_ITEM_ALLOWED_CHANGE_TYPE_MAP.includes(item.value); }), ]; + // Adding hardcoded EPIC till we have epic conversion support + // https://gitlab.com/gitlab-org/gitlab/-/issues/478486 + if (this.allowedWorkItemTypesEE.length > 0) { + allowedWorkItemTypes = [...allowedWorkItemTypes, ...this.allowedWorkItemTypesEE]; + } + + return allowedWorkItemTypes; }, isOkrsEnabled() { return this.hasOkrsFeature && this.glFeatures.okrsMvc; }, selectedWorkItemTypeWidgetDefinitions() { - return this.getWidgetDefinitions(this.selectedWorkItemType?.text); + return this.selectedWorkItemType?.value === WORK_ITEM_TYPE_ENUM_EPIC + ? this.getEpicWidgetDefinitions({ workItemTypes: this.workItemTypes }) + : this.getWidgetDefinitions(this.selectedWorkItemType?.text); }, currentWorkItemTypeWidgetDefinitions() { return this.getWidgetDefinitions(this.workItemType); @@ -200,6 +242,9 @@ export default { })); }, hasWidgetDifference() { + if (this.hasParent || this.hasChildren) { + return false; + } return this.widgetsWithExistingData.length > 0; }, parentWorkItem() { @@ -209,7 +254,7 @@ export default { return this.parentWorkItem?.workItemType?.name; }, workItemTypeId() { - return this.workItemTypes.find((type) => type.name === this.selectedWorkItemType.text).id; + return this.workItemTypes.find((type) => type.name === this.selectedWorkItemType?.text).id; }, selectedWorkItemTypeValue() { return this.selectedWorkItemType?.value || null; @@ -223,9 +268,19 @@ export default { }, }; }, + isWorkItemTypesQueryLoading() { + return this.$apollo.queries.workItemTypes.loading; + }, }, methods: { - async changeType() { + changeType() { + if (this.selectedWorkItemType.value === WORK_ITEM_TYPE_ENUM_EPIC) { + this.$emit('promoteToEpic'); + } else { + this.convertType(); + } + }, + async convertType() { try { const { data: { @@ -240,15 +295,15 @@ export default { }, }, }); - if (errors.length > 0) { - this.showErrorMessage(errors[0]); + if (errors?.length > 0) { + this.throwError(errors[0]); return; } this.$toast.show(s__('WorkItem|Type changed.')); this.$emit('workItemTypeChanged'); this.hide(); } catch (error) { - this.showErrorMessage(error); + this.throwError(error.message); Sentry.captureException(error); } }, @@ -258,9 +313,9 @@ export default { } return this.workItemTypes.find((widget) => widget.name === type)?.widgetDefinitions; }, - validateWorkItemType(value) { - this.changeTypeDisabled = false; - this.warningMessage = ''; + updateWorkItemFullPath(value) { + this.typeFieldNote = ''; + if (!value) { this.resetModal(); return; @@ -270,27 +325,40 @@ export default { (item) => item.value === value, ); + if (value === WORK_ITEM_TYPE_ENUM_EPIC) { + // triggers the `workItemTypes` to fetch Epic widget definitions + this.workItemFullPath = this.fullPath.substring(0, this.fullPath.lastIndexOf('/')); + this.typeFieldNote = this.epicFieldNote; + } + this.validateWorkItemType(); + }, + validateWorkItemType() { + this.changeTypeDisabled = false; + this.warningMessage = ''; + if (this.hasParent) { - this.showWarningMessage( - sprintfWorkItem( - I18N_WORK_ITEM_CHANGE_TYPE_PARENT_ERROR, - this.selectedWorkItemType.text, - this.parentWorkItemType, - ), + this.warningMessage = sprintfWorkItem( + I18N_WORK_ITEM_CHANGE_TYPE_PARENT_ERROR, + this.selectedWorkItemType.value === WORK_ITEM_TYPE_ENUM_EPIC + ? WORK_ITEM_TYPE_VALUE_EPIC + : this.selectedWorkItemType.text, + this.parentWorkItemType, ); + this.changeTypeDisabled = true; return; } if (this.hasChildren) { - const msg = sprintf(I18N_WORK_ITEM_CHANGE_TYPE_CHILD_ERROR, { + this.warningMessage = sprintf(I18N_WORK_ITEM_CHANGE_TYPE_CHILD_ERROR, { workItemType: capitalizeFirstCharacter( - this.selectedWorkItemType.text.toLocaleLowerCase(), + this.selectedWorkItemType.value === WORK_ITEM_TYPE_ENUM_EPIC + ? WORK_ITEM_TYPE_VALUE_EPIC.toLocaleLowerCase() + : this.selectedWorkItemType.text.toLocaleLowerCase(), ), childItemType: this.allowedChildTypes?.[0]?.name?.toLocaleLowerCase(), }); - this.showWarningMessage(msg); this.changeTypeDisabled = true; return; } @@ -299,15 +367,14 @@ export default { if (this.hasWidgetDifference) { this.warningMessage = sprintfWorkItem( I18N_WORK_ITEM_CHANGE_TYPE_MISSING_FIELDS_ERROR, - this.selectedWorkItemType.text, + this.selectedWorkItemType.value === WORK_ITEM_TYPE_ENUM_EPIC + ? WORK_ITEM_TYPE_VALUE_EPIC + : this.selectedWorkItemType.text, ); } }, - showWarningMessage(message) { - this.warningMessage = message; - }, - showErrorMessage(message) { - this.errorMessage = message; + throwError(message) { + this.$emit('error', message); }, show() { this.resetModal(); @@ -320,10 +387,10 @@ export default { }, resetModal() { this.warningMessage = ''; - this.errorMessage = ''; this.showDifferenceMessage = false; this.selectedWorkItemType = null; this.changeTypeDisabled = false; + this.typeFieldNote = ''; }, }, }; @@ -341,30 +408,23 @@ export default { @primary="changeType" @canceled="hide" > - - {{ errorMessage }} -
{{ s__('WorkItem|Select which type you would like to change this item to.') }}
+

{{ typeFieldNote }}

diff --git a/app/assets/javascripts/work_items/components/work_item_drawer.vue b/app/assets/javascripts/work_items/components/work_item_drawer.vue index ae43e08a460..ab03f15db2b 100644 --- a/app/assets/javascripts/work_items/components/work_item_drawer.vue +++ b/app/assets/javascripts/work_items/components/work_item_drawer.vue @@ -74,12 +74,14 @@ export default { activeItem: { deep: true, immediate: true, - handler(newValue) { + handler(newValue, oldValue) { if (newValue?.iid) { this.setDrawerParams(); // focus on header link when drawer is updated this.$nextTick(() => { - this.focusOnHeaderLink(); + if (!oldValue || oldValue?.iid !== newValue?.iid) { + this.focusOnHeaderLink(); + } }); } }, diff --git a/app/assets/javascripts/work_items/components/work_item_links/work_item_links_form.vue b/app/assets/javascripts/work_items/components/work_item_links/work_item_links_form.vue index f7a5a6383b5..2e92b0e2399 100644 --- a/app/assets/javascripts/work_items/components/work_item_links/work_item_links_form.vue +++ b/app/assets/javascripts/work_items/components/work_item_links/work_item_links_form.vue @@ -301,6 +301,7 @@ export default { markFormSubmitInProgress(value) { this.submitInProgress = value; this.$emit('update-in-progress', this.submitInProgress); + if (!value) this.$refs.wiTitleInput?.$el?.focus(); }, addChild() { this.markFormSubmitInProgress(true); @@ -340,7 +341,6 @@ export default { } else { this.unsetError(); this.workItemsToAdd = []; - this.closeForm(); } }) .catch(() => { @@ -379,7 +379,6 @@ export default { } else { this.unsetError(); this.$emit('addChild'); - this.closeForm(); } }) .catch(() => { diff --git a/app/assets/javascripts/work_items/components/work_item_sticky_header.vue b/app/assets/javascripts/work_items/components/work_item_sticky_header.vue index 1cd36e3a5d1..1f40bd7659a 100644 --- a/app/assets/javascripts/work_items/components/work_item_sticky_header.vue +++ b/app/assets/javascripts/work_items/components/work_item_sticky_header.vue @@ -85,6 +85,11 @@ export default { required: false, default: () => [], }, + namespaceFullName: { + type: String, + required: false, + default: '', + }, }, computed: { canUpdate() { @@ -197,6 +202,7 @@ export default { :widgets="widgets" :allowed-child-types="allowedChildTypes" :parent-id="parentId" + :namespace-full-name="namespaceFullName" @deleteWorkItem="$emit('deleteWorkItem')" @toggleWorkItemConfidentiality=" $emit('toggleWorkItemConfidentiality', !workItem.confidential) diff --git a/app/assets/javascripts/work_items/graphql/cache_utils.js b/app/assets/javascripts/work_items/graphql/cache_utils.js index d410709d146..77ebb4d443d 100644 --- a/app/assets/javascripts/work_items/graphql/cache_utils.js +++ b/app/assets/javascripts/work_items/graphql/cache_utils.js @@ -568,6 +568,7 @@ export const setNewWorkItemCache = async ( id: newWorkItemPath, fullPath, name: newWorkItemPath, + fullName: newWorkItemPath, __typename: 'Namespace', }, author: { diff --git a/app/assets/javascripts/work_items/graphql/work_item.fragment.graphql b/app/assets/javascripts/work_items/graphql/work_item.fragment.graphql index 9dcfd9dec13..91bb1068dd5 100644 --- a/app/assets/javascripts/work_items/graphql/work_item.fragment.graphql +++ b/app/assets/javascripts/work_items/graphql/work_item.fragment.graphql @@ -21,6 +21,7 @@ fragment WorkItem on WorkItem { id fullPath name + fullName } author { ...Author diff --git a/app/assets/javascripts/work_items/graphql/workspace_permissions.query.graphql b/app/assets/javascripts/work_items/graphql/workspace_permissions.query.graphql index 8f1a3020ab8..b253e3dc1cd 100644 --- a/app/assets/javascripts/work_items/graphql/workspace_permissions.query.graphql +++ b/app/assets/javascripts/work_items/graphql/workspace_permissions.query.graphql @@ -3,6 +3,7 @@ query workspacePermissions($fullPath: ID!) { id userPermissions { createDesign + moveDesign } } } diff --git a/app/controllers/repositories/git_http_client_controller.rb b/app/controllers/repositories/git_http_client_controller.rb index c7c8e3c83c7..10e5e45cbf5 100644 --- a/app/controllers/repositories/git_http_client_controller.rb +++ b/app/controllers/repositories/git_http_client_controller.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Repositories - class GitHttpClientController < Repositories::ApplicationController + class GitHttpClientController < ::Repositories::ApplicationController include ActionController::HttpAuthentication::Basic include KerberosHelper include Gitlab::Utils::StrongMemoize @@ -153,4 +153,4 @@ module Repositories end end -Repositories::GitHttpClientController.prepend_mod_with('Repositories::GitHttpClientController') +::Repositories::GitHttpClientController.prepend_mod_with('Repositories::GitHttpClientController') diff --git a/app/controllers/repositories/git_http_controller.rb b/app/controllers/repositories/git_http_controller.rb index 94972f6593c..147f4751a48 100644 --- a/app/controllers/repositories/git_http_controller.rb +++ b/app/controllers/repositories/git_http_controller.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Repositories - class GitHttpController < Repositories::GitHttpClientController + class GitHttpController < ::Repositories::GitHttpClientController include WorkhorseRequest before_action :access_check @@ -152,4 +152,4 @@ module Repositories end end -Repositories::GitHttpController.prepend_mod_with('Repositories::GitHttpController') +::Repositories::GitHttpController.prepend_mod_with('Repositories::GitHttpController') diff --git a/app/controllers/repositories/lfs_api_controller.rb b/app/controllers/repositories/lfs_api_controller.rb index c1b7e21a906..b8c5970e088 100644 --- a/app/controllers/repositories/lfs_api_controller.rb +++ b/app/controllers/repositories/lfs_api_controller.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Repositories - class LfsApiController < Repositories::GitHttpClientController + class LfsApiController < ::Repositories::GitHttpClientController include LfsRequest include Gitlab::Utils::StrongMemoize @@ -211,4 +211,4 @@ module Repositories end end -Repositories::LfsApiController.prepend_mod_with('Repositories::LfsApiController') +::Repositories::LfsApiController.prepend_mod_with('Repositories::LfsApiController') diff --git a/app/controllers/repositories/lfs_locks_api_controller.rb b/app/controllers/repositories/lfs_locks_api_controller.rb index fe66fe983b7..aa6a7e9ad2a 100644 --- a/app/controllers/repositories/lfs_locks_api_controller.rb +++ b/app/controllers/repositories/lfs_locks_api_controller.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Repositories - class LfsLocksApiController < Repositories::GitHttpClientController + class LfsLocksApiController < ::Repositories::GitHttpClientController include LfsRequest # added here as a part of the refactor, will be removed diff --git a/app/controllers/repositories/lfs_storage_controller.rb b/app/controllers/repositories/lfs_storage_controller.rb index 7aa117b39a6..e545f63bfd7 100644 --- a/app/controllers/repositories/lfs_storage_controller.rb +++ b/app/controllers/repositories/lfs_storage_controller.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Repositories - class LfsStorageController < Repositories::GitHttpClientController + class LfsStorageController < ::Repositories::GitHttpClientController include LfsRequest include WorkhorseRequest include SendFileUpload diff --git a/app/graphql/resolvers/repository_branch_names_resolver.rb b/app/graphql/resolvers/repository_branch_names_resolver.rb index 96550bce32f..faf1bd41429 100644 --- a/app/graphql/resolvers/repository_branch_names_resolver.rb +++ b/app/graphql/resolvers/repository_branch_names_resolver.rb @@ -19,7 +19,7 @@ module Resolvers description: 'Number of branch names to return.' def resolve(search_pattern:, offset:, limit:) - Repositories::BranchNamesFinder.new(object, offset: offset, limit: limit, search: search_pattern).execute + ::Repositories::BranchNamesFinder.new(object, offset: offset, limit: limit, search: search_pattern).execute end end end diff --git a/app/models/commit.rb b/app/models/commit.rb index cd593d66724..51a114a2679 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -16,7 +16,7 @@ class Commit include ActsAsPaginatedDiff include CacheMarkdownField include GlobalID::Identification - include Repositories::StreamableDiff + include ::Repositories::StreamableDiff participant :author participant :committer diff --git a/app/models/compare.rb b/app/models/compare.rb index d7164c401a6..eb516cdd0fa 100644 --- a/app/models/compare.rb +++ b/app/models/compare.rb @@ -3,7 +3,7 @@ class Compare include Gitlab::Utils::StrongMemoize include ActsAsPaginatedDiff - include Repositories::StreamableDiff + include ::Repositories::StreamableDiff delegate :same, :head, :base, :generated_files, to: :@compare diff --git a/app/models/concerns/has_repository.rb b/app/models/concerns/has_repository.rb index eadd74f77bb..c6f93f14b1d 100644 --- a/app/models/concerns/has_repository.rb +++ b/app/models/concerns/has_repository.rb @@ -125,7 +125,7 @@ module HasRepository reload_default_branch Gitlab::EventStore.publish( - Repositories::DefaultBranchChangedEvent.new(data: { container_id: id, container_type: self.class.name })) + ::Repositories::DefaultBranchChangedEvent.new(data: { container_id: id, container_type: self.class.name })) end def after_change_head_branch_does_not_exist(branch) diff --git a/app/models/project.rb b/app/models/project.rb index eb74e54c59e..8902110284e 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -33,7 +33,7 @@ class Project < ApplicationRecord include FeatureGate include OptionallySearch include FromUnion - include Repositories::CanHousekeepRepository + include ::Repositories::CanHousekeepRepository include EachBatch include GitlabRoutingHelper include BulkMemberAccessLoad diff --git a/app/models/wiki.rb b/app/models/wiki.rb index a96236fd3fb..e709de86068 100644 --- a/app/models/wiki.rb +++ b/app/models/wiki.rb @@ -3,7 +3,7 @@ class Wiki extend ::Gitlab::Utils::Override include HasRepository - include Repositories::CanHousekeepRepository + include ::Repositories::CanHousekeepRepository include Gitlab::Utils::StrongMemoize include GlobalID::Identification include Gitlab::Git::WrapsGitalyErrors diff --git a/app/services/concerns/update_repository_storage_methods.rb b/app/services/concerns/update_repository_storage_methods.rb index f1b614bfa32..d36efe08b1b 100644 --- a/app/services/concerns/update_repository_storage_methods.rb +++ b/app/services/concerns/update_repository_storage_methods.rb @@ -99,7 +99,7 @@ module UpdateRepositoryStorageMethods object_pool = repository.project&.pool_repository&.object_pool hint = object_pool ? object_pool.relative_path : "" - Repositories::ReplicateService.new(raw_repository) + ::Repositories::ReplicateService.new(raw_repository) .execute(new_repository, type.name, partition_hint: hint) end diff --git a/app/services/git/process_ref_changes_service.rb b/app/services/git/process_ref_changes_service.rb index d959d66a180..fba6b3c82f0 100644 --- a/app/services/git/process_ref_changes_service.rb +++ b/app/services/git/process_ref_changes_service.rb @@ -135,10 +135,10 @@ module Git end def perform_housekeeping - housekeeping = Repositories::HousekeepingService.new(project) + housekeeping = ::Repositories::HousekeepingService.new(project) housekeeping.increment! housekeeping.execute if housekeeping.needed? - rescue Repositories::HousekeepingService::LeaseTaken + rescue ::Repositories::HousekeepingService::LeaseTaken end def process_commit_worker_pool diff --git a/app/services/git/wiki_push_service.rb b/app/services/git/wiki_push_service.rb index 11aeb650a5b..1d277a88f23 100644 --- a/app/services/git/wiki_push_service.rb +++ b/app/services/git/wiki_push_service.rb @@ -77,10 +77,10 @@ module Git end def perform_housekeeping - housekeeping = Repositories::HousekeepingService.new(wiki) + housekeeping = ::Repositories::HousekeepingService.new(wiki) housekeeping.increment! housekeeping.execute if housekeeping.needed? - rescue Repositories::HousekeepingService::LeaseTaken + rescue ::Repositories::HousekeepingService::LeaseTaken # no-op end end diff --git a/app/services/projects/destroy_service.rb b/app/services/projects/destroy_service.rb index dbf2e1e5c9b..41d97841c10 100644 --- a/app/services/projects/destroy_service.rb +++ b/app/services/projects/destroy_service.rb @@ -136,7 +136,7 @@ module Projects def remove_repository(repository) return true unless repository - result = Repositories::DestroyService.new(repository).execute + result = ::Repositories::DestroyService.new(repository).execute result[:status] == :success end diff --git a/app/services/projects/update_repository_storage_service.rb b/app/services/projects/update_repository_storage_service.rb index 8387ed593dc..c846cc39001 100644 --- a/app/services/projects/update_repository_storage_service.rb +++ b/app/services/projects/update_repository_storage_service.rb @@ -50,7 +50,7 @@ module Projects ) begin - Repositories::ReplicateService.new(pool_repository.object_pool.repository) + ::Repositories::ReplicateService.new(pool_repository.object_pool.repository) .execute(target_pool_repository.object_pool.repository, :object_pool) rescue StandardError => e target_pool_repository.destroy! diff --git a/app/services/repositories/destroy_service.rb b/app/services/repositories/destroy_service.rb index a87b8d09244..f7b78b6a78c 100644 --- a/app/services/repositories/destroy_service.rb +++ b/app/services/repositories/destroy_service.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class Repositories::DestroyService < Repositories::BaseService +class Repositories::DestroyService < ::Repositories::BaseService def execute return success unless repository return success unless repo_exists?(disk_path) diff --git a/app/services/repositories/housekeeping_service.rb b/app/services/repositories/housekeeping_service.rb index f314e210442..587fcca64af 100644 --- a/app/services/repositories/housekeeping_service.rb +++ b/app/services/repositories/housekeeping_service.rb @@ -3,8 +3,8 @@ # Used for git housekeeping # # Ex. -# Repositories::HousekeepingService.new(project).execute -# Repositories::HousekeepingService.new(project.wiki).execute +# ::Repositories::HousekeepingService.new(project).execute +# ::Repositories::HousekeepingService.new(project.wiki).execute # module Repositories class HousekeepingService < BaseService diff --git a/app/services/repositories/replicate_service.rb b/app/services/repositories/replicate_service.rb index ee9088dd86a..e222d2d1377 100644 --- a/app/services/repositories/replicate_service.rb +++ b/app/services/repositories/replicate_service.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Repositories - class ReplicateService < Repositories::BaseService + class ReplicateService < ::Repositories::BaseService Error = Class.new(StandardError) def execute(new_repository, type, partition_hint: "") diff --git a/app/services/repositories/rewrite_history_service.rb b/app/services/repositories/rewrite_history_service.rb index 2d49dd4c8f0..10d15086bc7 100644 --- a/app/services/repositories/rewrite_history_service.rb +++ b/app/services/repositories/rewrite_history_service.rb @@ -19,7 +19,7 @@ module Repositories result = validate_input(blob_oids: blob_oids, redactions: redactions) return result if result.error? - Repositories::RewriteHistoryWorker.perform_async( + ::Repositories::RewriteHistoryWorker.perform_async( project_id: project.id, user_id: current_user.id, blob_oids: blob_oids, diff --git a/app/services/snippets/bulk_destroy_service.rb b/app/services/snippets/bulk_destroy_service.rb index 9c6e1c14051..6a37c6ab4e2 100644 --- a/app/services/snippets/bulk_destroy_service.rb +++ b/app/services/snippets/bulk_destroy_service.rb @@ -47,7 +47,7 @@ module Snippets def attempt_delete_repositories! snippets.each do |snippet| - result = Repositories::DestroyService.new(snippet.repository).execute + result = ::Repositories::DestroyService.new(snippet.repository).execute raise DeleteRepositoryError if result[:status] == :error end diff --git a/app/services/snippets/destroy_service.rb b/app/services/snippets/destroy_service.rb index 6c62d7d5e45..0e482e77062 100644 --- a/app/services/snippets/destroy_service.rb +++ b/app/services/snippets/destroy_service.rb @@ -37,7 +37,7 @@ module Snippets private def attempt_destroy! - result = Repositories::DestroyService.new(snippet.repository).execute + result = ::Repositories::DestroyService.new(snippet.repository).execute raise DestroyError if result[:status] == :error diff --git a/app/workers/object_pool/join_worker.rb b/app/workers/object_pool/join_worker.rb index 36094ddbe84..72caee09f72 100644 --- a/app/workers/object_pool/join_worker.rb +++ b/app/workers/object_pool/join_worker.rb @@ -19,7 +19,7 @@ module ObjectPool project.link_pool_repository - Repositories::HousekeepingService.new(project).execute + ::Repositories::HousekeepingService.new(project).execute end end end diff --git a/app/workers/projects/after_import_worker.rb b/app/workers/projects/after_import_worker.rb index ff6776e5f73..c4faa94034e 100644 --- a/app/workers/projects/after_import_worker.rb +++ b/app/workers/projects/after_import_worker.rb @@ -14,7 +14,7 @@ module Projects def perform(project_id) @project = Project.find(project_id) - service = Repositories::HousekeepingService.new(@project) + service = ::Repositories::HousekeepingService.new(@project) service.execute do import_failure_service.with_retry(action: 'delete_all_refs') do @@ -26,7 +26,7 @@ module Projects # import actually changed, so we increment the counter to avoid # causing GC to run every time. service.increment! - rescue Repositories::HousekeepingService::LeaseTaken => e + rescue ::Repositories::HousekeepingService::LeaseTaken => e ::Import::Framework::Logger.info( message: 'Project housekeeping failed', project_full_path: @project.full_path, diff --git a/app/workers/repositories/rewrite_history_worker.rb b/app/workers/repositories/rewrite_history_worker.rb index 1e810f3fbea..749d1b29624 100644 --- a/app/workers/repositories/rewrite_history_worker.rb +++ b/app/workers/repositories/rewrite_history_worker.rb @@ -19,7 +19,7 @@ module Repositories user = User.find_by_id(args[:user_id]) return unless user - result = Repositories::RewriteHistoryService.new(project, user).execute( + result = ::Repositories::RewriteHistoryService.new(project, user).execute( blob_oids: args.fetch(:blob_oids, []), redactions: args.fetch(:redactions, []) ) diff --git a/doc/user/application_security/dast/on-demand_scan.md b/doc/user/application_security/dast/on-demand_scan.md index 4a1bb393032..fb2f38313d3 100644 --- a/doc/user/application_security/dast/on-demand_scan.md +++ b/doc/user/application_security/dast/on-demand_scan.md @@ -133,6 +133,7 @@ To delete an on-demand scan: > - Site profile features, scan method and file URL, were [enabled on GitLab.com and GitLab Self-Managed](https://gitlab.com/gitlab-org/gitlab/-/issues/345837) in GitLab 15.6. > - GraphQL endpoint path feature was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/378692) in GitLab 15.7. +> - Additional variables [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/177703) in GitLab 17.9. A site profile defines the attributes and configuration details of the deployed application, website, or API to be scanned by DAST. A site profile can be referenced in `.gitlab-ci.yml` and @@ -157,6 +158,7 @@ A site profile contains: - **Scan method**: A type of method to perform API testing. The supported methods are OpenAPI, Postman Collections, HTTP Archive (HAR), or GraphQL. - **GraphQL endpoint path**: The path to the GraphQL endpoint. This path is concatenated with the target URL to provide the URI for the scan to test. The GraphQL endpoint must support introspection queries. - **File URL**: The URL of the OpenAPI, Postman Collection, or HTTP Archive file. +- **Additional variables**: A list of environment variables to configure specific scan behaviors. These variables provide the same configuration options as pipeline-based DAST scans, such as setting timeouts, adding an authentication success URL, or enabling advanced scan features. When an API site type is selected, a host override is used to ensure the API being scanned is on the same host as the target. This is done to reduce the risk of running an active scan against the wrong API. diff --git a/lib/gitlab/github_import/importer/repository_importer.rb b/lib/gitlab/github_import/importer/repository_importer.rb index d37942aa8a3..79515e43d13 100644 --- a/lib/gitlab/github_import/importer/repository_importer.rb +++ b/lib/gitlab/github_import/importer/repository_importer.rb @@ -58,7 +58,7 @@ module Gitlab # The initial fetch can bring in lots of loose refs and objects. # Running a `git gc` will make importing pull requests faster. - Repositories::HousekeepingService.new(project, :gc).execute + ::Repositories::HousekeepingService.new(project, :gc).execute true end diff --git a/lib/gitlab/import_export/repo_restorer.rb b/lib/gitlab/import_export/repo_restorer.rb index 1861a92100e..d8389535d3e 100644 --- a/lib/gitlab/import_export/repo_restorer.rb +++ b/lib/gitlab/import_export/repo_restorer.rb @@ -45,10 +45,10 @@ module Gitlab message: %(Deleting existing "#{repository.disk_path}" to re-import it.) ) - Repositories::DestroyService.new(repository).execute + ::Repositories::DestroyService.new(repository).execute # Because Gitlab::Git::Repository#remove happens inside a run_after_commit - # callback in the Repositories::DestroyService#execute we need to trigger + # callback in the ::Repositories::DestroyService#execute we need to trigger # the callback. repository.project.touch end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 3f4f6eda46f..e010ea6199b 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -2776,6 +2776,9 @@ msgstr "" msgid "AbuseReport|Reported profile" msgstr "" +msgid "AbuseReport|Reporter" +msgstr "" + msgid "AbuseReport|Screenshot of reported abuse" msgstr "" @@ -22703,6 +22706,9 @@ msgstr "" msgid "Epic" msgstr "" +msgid "Epic (Promote to group)" +msgstr "" + msgid "Epic Boards" msgstr "" @@ -64588,6 +64594,9 @@ msgstr "" msgid "WorkItem|Epic" msgstr "" +msgid "WorkItem|Epic will be moved to parent group %{groupName}." +msgstr "" + msgid "WorkItem|Existing %{workItemName}" msgstr "" diff --git a/scripts/lint-docs-redirects.rb b/scripts/lint-docs-redirects.rb index 36567571397..da5de58b5f0 100755 --- a/scripts/lint-docs-redirects.rb +++ b/scripts/lint-docs-redirects.rb @@ -74,11 +74,23 @@ class LintDocsRedirect ## The navigation.yaml equivalent is: ee/administration/appearance.html ## def check_for_missing_nav_entry(file) - file_sub = file["old_path"].gsub('doc', project_slug).gsub('index.md', '').gsub('.md', '.html') + file_sub = file["old_path"].gsub('doc', project_slug).gsub(/_?index\.md/, '').gsub('.md', + '.html') result = navigation_file.include?(file_sub) return unless result + # If we're here, the path exists in navigation + # Now check if this is a rename between index.md and _index.md + if renamed_doc_file?(file) + old_basename = File.basename(file['old_path']) + new_basename = File.basename(file['new_path']) + + # Allow renames between index.md and _index.md + return if %w[index.md _index.md].include?(old_basename) && + %w[index.md _index.md].include?(new_basename) + end + warning(file) abort diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index eeb21a52877..757f85df70e 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -654,7 +654,7 @@ RSpec.describe ProjectsController, feature_category: :groups_and_projects do describe '#housekeeping' do let_it_be(:group) { create(:group) } - let(:housekeeping_service_dbl) { instance_double(Repositories::HousekeepingService) } + let(:housekeeping_service_dbl) { instance_double(::Repositories::HousekeepingService) } let(:params) do { namespace_id: project.namespace.path, @@ -665,7 +665,7 @@ RSpec.describe ProjectsController, feature_category: :groups_and_projects do let(:prune) { nil } let_it_be(:project) { create(:project, group: group) } - let(:housekeeping) { Repositories::HousekeepingService.new(project) } + let(:housekeeping) { ::Repositories::HousekeepingService.new(project) } subject { post :housekeeping, params: params } @@ -674,7 +674,7 @@ RSpec.describe ProjectsController, feature_category: :groups_and_projects do group.add_owner(user) sign_in(user) - allow(Repositories::HousekeepingService).to receive(:new).with(project, :eager).and_return(housekeeping) + allow(::Repositories::HousekeepingService).to receive(:new).with(project, :eager).and_return(housekeeping) end it 'forces a full garbage collection' do @@ -707,7 +707,7 @@ RSpec.describe ProjectsController, feature_category: :groups_and_projects do let(:prune) { true } it 'enqueues pruning' do - allow(Repositories::HousekeepingService).to receive(:new).with(project, :prune).and_return(housekeeping_service_dbl) + allow(::Repositories::HousekeepingService).to receive(:new).with(project, :prune).and_return(housekeeping_service_dbl) expect(housekeeping_service_dbl).to receive(:execute) subject diff --git a/spec/features/work_items/work_item_detail_spec.rb b/spec/features/work_items/work_item_detail_spec.rb index 5a25675f4a4..6a33e75fe9a 100644 --- a/spec/features/work_items/work_item_detail_spec.rb +++ b/spec/features/work_items/work_item_detail_spec.rb @@ -129,7 +129,7 @@ RSpec.describe 'Work item detail', :js, feature_category: :team_planning do it 'change type action is not displayed' do click_button _('More actions'), match: :first - expect(find_by_testid('work-item-actions-dropdown')).to have_button(s_('WorkItem|Change type')) + expect(find_by_testid('work-item-actions-dropdown')).not_to have_button(s_('WorkItem|Change type')) end end end diff --git a/spec/frontend/work_items/components/design_management/design_management_widget_spec.js b/spec/frontend/work_items/components/design_management/design_management_widget_spec.js index 1718d7b19ba..6ad1c5d910e 100644 --- a/spec/frontend/work_items/components/design_management/design_management_widget_spec.js +++ b/spec/frontend/work_items/components/design_management/design_management_widget_spec.js @@ -98,6 +98,7 @@ describe('DesignWidget', () => { routeArg = MOCK_ROUTE, uploadError = null, uploadErrorVariant = ALERT_VARIANTS.danger, + canReorderDesign = true, } = {}) { wrapper = shallowMountExtended(DesignWidget, { isLoggedIn: isLoggedIn(), @@ -110,6 +111,7 @@ describe('DesignWidget', () => { workItemId, uploadError, uploadErrorVariant, + canReorderDesign, }, directives: { GlTooltip: createMockDirective('gl-tooltip'), @@ -163,6 +165,14 @@ describe('DesignWidget', () => { it('renders VueDraggable component', () => { expect(findVueDraggable().exists()).toBe(true); + expect(findVueDraggable().vm.$attrs.disabled).toBe(false); + }); + + it('renders VueDraggable component with dragging disabled when canReorderDesign prop is false', async () => { + await createComponent({ canReorderDesign: false }); + await waitForPromises(); + + expect(findVueDraggable().vm.$attrs.disabled).toBe(true); }); it('calls moveDesignMutation with correct parameters and reorders designs', async () => { diff --git a/spec/frontend/work_items/components/work_item_actions_spec.js b/spec/frontend/work_items/components/work_item_actions_spec.js index 553eac77053..cf8f38a3078 100644 --- a/spec/frontend/work_items/components/work_item_actions_spec.js +++ b/spec/frontend/work_items/components/work_item_actions_spec.js @@ -16,7 +16,7 @@ import WorkItemActions from '~/work_items/components/work_item_actions.vue'; import WorkItemAbuseModal from '~/work_items/components/work_item_abuse_modal.vue'; import WorkItemStateToggle from '~/work_items/components/work_item_state_toggle.vue'; import CreateWorkItemModal from '~/work_items/components/create_work_item_modal.vue'; -import WorkItemChangeTypeModal from '~/work_items/components/work_item_change_type_modal.vue'; +import WorkItemChangeTypeModal from 'ee_else_ce/work_items/components/work_item_change_type_modal.vue'; import { STATE_OPEN, TEST_ID_CONFIDENTIALITY_TOGGLE_ACTION, diff --git a/spec/frontend/work_items/components/work_item_change_type_modal_spec.js b/spec/frontend/work_items/components/work_item_change_type_modal_spec.js index d301e9579d2..a53b9a8706c 100644 --- a/spec/frontend/work_items/components/work_item_change_type_modal_spec.js +++ b/spec/frontend/work_items/components/work_item_change_type_modal_spec.js @@ -41,6 +41,7 @@ describe('WorkItemChangeTypeModal component', () => { const convertWorkItemMutationSuccessHandler = jest .fn() .mockResolvedValue(convertWorkItemMutationResponse); + const graphqlError = 'GraphQL error'; const convertWorkItemMutationErrorResponse = { errors: [ @@ -52,6 +53,7 @@ describe('WorkItemChangeTypeModal component', () => { workItemConvert: null, }, }; + const noDesignQueryHandler = jest.fn().mockResolvedValue(designCollectionResponse([])); const oneDesignQueryHandler = jest.fn().mockResolvedValue(designCollectionResponse([mockDesign])); @@ -63,6 +65,7 @@ describe('WorkItemChangeTypeModal component', () => { widgets = [], workItemType = WORK_ITEM_TYPE_VALUE_TASK, convertWorkItemMutationHandler = convertWorkItemMutationSuccessHandler, + designQueryHandler = noDesignQueryHandler, } = {}) => { wrapper = mountExtended(WorkItemChangeTypeModal, { @@ -74,6 +77,7 @@ describe('WorkItemChangeTypeModal component', () => { propsData: { workItemId: 'gid://gitlab/WorkItem/1', fullPath: 'gitlab-org/gitlab-test', + workItemIid: '1', hasParent, hasChildren, widgets, @@ -98,7 +102,6 @@ describe('WorkItemChangeTypeModal component', () => { const findChangeTypeModal = () => wrapper.findComponent(GlModal); const findGlFormSelect = () => wrapper.findComponent(GlFormSelect); const findWarningAlert = () => wrapper.findByTestId('change-type-warning-message'); - const findErrorAlert = () => wrapper.findByTestId('change-type-error-message'); beforeEach(async () => { createComponent(); @@ -137,6 +140,7 @@ describe('WorkItemChangeTypeModal component', () => { findGlFormSelect().vm.$emit('change', WORK_ITEM_TYPE_ENUM_KEY_RESULT); await nextTick(); + await waitForPromises(); expect(findWarningAlert().text()).toBe( 'Parent item type issue is not supported on key result. Remove the parent item to change type.', @@ -151,6 +155,7 @@ describe('WorkItemChangeTypeModal component', () => { findGlFormSelect().vm.$emit('change', WORK_ITEM_TYPE_ENUM_KEY_RESULT); await nextTick(); + await waitForPromises(); expect(findWarningAlert().text()).toBe( 'Key result does not support the task child item types. Remove child items to change type.', @@ -226,9 +231,9 @@ describe('WorkItemChangeTypeModal component', () => { }); it.each` - errorType | expectedErrorMessage | failureHandler - ${'graphql error'} | ${graphqlError} | ${jest.fn().mockResolvedValue(convertWorkItemMutationErrorResponse)} - ${'network error'} | ${'Error: Network error'} | ${jest.fn().mockRejectedValue(new Error('Network error'))} + errorType | expectedErrorMessage | failureHandler + ${'graphql error'} | ${graphqlError} | ${jest.fn().mockResolvedValue(convertWorkItemMutationErrorResponse)} + ${'network error'} | ${'Network error'} | ${jest.fn().mockRejectedValue(new Error('Network error'))} `( 'emits an error when there is a $errorType', async ({ expectedErrorMessage, failureHandler }) => { @@ -246,7 +251,7 @@ describe('WorkItemChangeTypeModal component', () => { await waitForPromises(); - expect(findErrorAlert().text()).toContain(expectedErrorMessage); + expect(wrapper.emitted('error')[0][0]).toEqual(expectedErrorMessage); }, ); }); diff --git a/spec/frontend/work_items/components/work_item_description_spec.js b/spec/frontend/work_items/components/work_item_description_spec.js index f1c61bc8982..f143a628733 100644 --- a/spec/frontend/work_items/components/work_item_description_spec.js +++ b/spec/frontend/work_items/components/work_item_description_spec.js @@ -162,6 +162,7 @@ describe('WorkItemDescription', () => { id: 'gid://gitlab/Group/24', fullPath: 'gitlab-org', name: 'Gitlab Org', + fullName: 'Gitlab Org', __typename: 'Namespace', }, }, diff --git a/spec/frontend/work_items/components/work_item_detail_spec.js b/spec/frontend/work_items/components/work_item_detail_spec.js index 15134933f8e..2e298d136d2 100644 --- a/spec/frontend/work_items/components/work_item_detail_spec.js +++ b/spec/frontend/work_items/components/work_item_detail_spec.js @@ -88,7 +88,9 @@ describe('WorkItemDetail component', () => { .mockResolvedValue(mockProjectPermissionsQueryResponse()); const workspacePermissionsNotAllowedHandler = jest .fn() - .mockResolvedValue(mockProjectPermissionsQueryResponse({ createDesign: false })); + .mockResolvedValue( + mockProjectPermissionsQueryResponse({ createDesign: false, moveDesign: false }), + ); const uploadSuccessDesignMutationHandler = jest .fn() .mockResolvedValue(mockUploadDesignMutationResponse); diff --git a/spec/frontend/work_items/components/work_item_links/work_item_links_form_spec.js b/spec/frontend/work_items/components/work_item_links/work_item_links_form_spec.js index f67c64c4947..e4217f9c2ad 100644 --- a/spec/frontend/work_items/components/work_item_links/work_item_links_form_spec.js +++ b/spec/frontend/work_items/components/work_item_links/work_item_links_form_spec.js @@ -200,7 +200,7 @@ describe('WorkItemLinksForm', () => { expect(wrapper.emitted('update-in-progress')[1]).toEqual([false]); }); - it('creates child task in non confidential parent and closes the form', async () => { + it('creates child task in non confidential parent', async () => { submitForm({ title: 'Create task test' }); expect(wrapper.emitted('update-in-progress')).toEqual([[true]]); @@ -219,7 +219,6 @@ describe('WorkItemLinksForm', () => { }, }); expect(wrapper.emitted('addChild')).toEqual([[]]); - expect(wrapper.emitted('cancel')).toEqual([[]]); expect(wrapper.emitted('update-in-progress')[1]).toEqual([false]); }); @@ -265,7 +264,7 @@ describe('WorkItemLinksForm', () => { expect(findWorkItemTokenInput().exists()).toBe(false); }); - it('creates child issue in non confidential parent and closes the form', async () => { + it('creates child issue in non confidential parent', async () => { submitForm({ title: 'Create issue test', fullPath: projectData[0].fullPath }); expect(wrapper.emitted('update-in-progress')).toEqual([[true]]); @@ -285,7 +284,6 @@ describe('WorkItemLinksForm', () => { }); expect(wrapper.emitted('addChild')).toEqual([[]]); expect(wrapper.emitted('update-in-progress')[1]).toEqual([false]); - expect(wrapper.emitted('cancel')).toEqual([[]]); }); it('creates child issue in confidential parent', async () => { @@ -459,7 +457,7 @@ describe('WorkItemLinksForm', () => { }); }); - it('selects, adds children and closes the form', async () => { + it('selects and adds children', async () => { await selectAvailableWorkItemTokens(); expect(findAddChildButton().text()).toBe('Add tasks'); @@ -473,7 +471,6 @@ describe('WorkItemLinksForm', () => { await waitForPromises(); expect(updateMutationResolver).toHaveBeenCalled(); - expect(wrapper.emitted('cancel')).toEqual([[]]); }); it('shows validation error when non-confidential child items are being added to confidential parent', async () => { diff --git a/spec/frontend/work_items/mock_data.js b/spec/frontend/work_items/mock_data.js index 7b091e9ce27..ea34e9129bd 100644 --- a/spec/frontend/work_items/mock_data.js +++ b/spec/frontend/work_items/mock_data.js @@ -198,6 +198,7 @@ export const workItemQueryResponse = { id: '1', fullPath: 'test-project-path', name: 'Project name', + fullName: 'Group name', }, workItemType: { __typename: 'WorkItemType', @@ -319,6 +320,7 @@ export const updateWorkItemMutationResponse = { id: '1', fullPath: 'test-project-path', name: 'Project name', + fullName: 'Group name', }, workItemType: { __typename: 'WorkItemType', @@ -454,6 +456,7 @@ export const convertWorkItemMutationResponse = { id: '1', fullPath: 'test-project-path', name: 'Project name', + fullName: 'Group name', }, workItemType: { __typename: 'WorkItemType', @@ -1397,6 +1400,7 @@ export const workItemResponseFactory = ({ id: '1', fullPath: 'test-project-path', name: 'Project name', + fullName: 'Group name', }, workItemType, userPermissions: { @@ -1764,6 +1768,7 @@ export const createWorkItemMutationResponse = { id: '1', fullPath: 'test-project-path', name: 'Project name', + fullName: 'Group name', }, workItemType: { __typename: 'WorkItemType', @@ -2342,6 +2347,7 @@ export const workItemObjectiveWithChild = { id: '1', fullPath: 'test-project-path', name: 'Project name', + fullName: 'Group name', }, userPermissions: { deleteWorkItem: true, @@ -2431,6 +2437,7 @@ export const workItemObjectiveWithoutChild = { id: '1', fullPath: 'test-project-path', name: 'Project name', + fullName: 'Group name', }, userPermissions: { deleteWorkItem: true, @@ -3028,6 +3035,7 @@ export const changeWorkItemParentMutationResponse = { id: '1', fullPath: 'test-project-path', name: 'Project name', + fullName: 'Group name', }, reference: 'test-project-path#2', createNoteEmail: @@ -5452,6 +5460,7 @@ export const createWorkItemQueryResponse = { id: 'full-path-epic-id', fullPath: 'full-path', name: 'Gitlab Org', + fullName: 'Group name', __typename: 'Namespace', }, author: { @@ -5803,12 +5812,16 @@ export const mockUserPreferences = (useWorkItemsView = true) => ({ }, }); -export const mockProjectPermissionsQueryResponse = ({ createDesign = true } = {}) => ({ +export const mockProjectPermissionsQueryResponse = ({ + createDesign = true, + moveDesign = true, +} = {}) => ({ data: { workspace: { id: 'gid://gitlab/Project/1', userPermissions: { createDesign, + moveDesign, __typename: 'ProjectPermissions', }, __typename: 'Project', diff --git a/spec/lib/bulk_imports/projects/pipelines/repository_pipeline_spec.rb b/spec/lib/bulk_imports/projects/pipelines/repository_pipeline_spec.rb index 04a37c6763b..fb0155375b1 100644 --- a/spec/lib/bulk_imports/projects/pipelines/repository_pipeline_spec.rb +++ b/spec/lib/bulk_imports/projects/pipelines/repository_pipeline_spec.rb @@ -89,9 +89,9 @@ RSpec.describe BulkImports::Projects::Pipelines::RepositoryPipeline, feature_cat describe '#after_run' do it 'executes housekeeping service after import' do - service = instance_double(Repositories::HousekeepingService) + service = instance_double(::Repositories::HousekeepingService) - expect(Repositories::HousekeepingService).to receive(:new).with(context.portable, :gc).and_return(service) + expect(::Repositories::HousekeepingService).to receive(:new).with(context.portable, :gc).and_return(service) expect(service).to receive(:execute) pipeline.after_run(context) diff --git a/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb b/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb index 6b3d4485ea5..8837c37b964 100644 --- a/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb @@ -208,7 +208,7 @@ RSpec.describe Gitlab::GithubImport::Importer::RepositoryImporter, feature_categ expect(importer).to receive(:validate_repository_size!) service = double - expect(Repositories::HousekeepingService) + expect(::Repositories::HousekeepingService) .to receive(:new).with(project, :gc).and_return(service) expect(service).to receive(:execute) diff --git a/spec/lib/gitlab/import_export/repo_restorer_spec.rb b/spec/lib/gitlab/import_export/repo_restorer_spec.rb index 3c540eb45c9..c4ff2e62dd3 100644 --- a/spec/lib/gitlab/import_export/repo_restorer_spec.rb +++ b/spec/lib/gitlab/import_export/repo_restorer_spec.rb @@ -46,7 +46,7 @@ RSpec.describe Gitlab::ImportExport::RepoRestorer do allow(project.repository).to receive(:exists?).and_return(true) allow(project.repository).to receive(:disk_path).and_return('repository_path') - expect_next_instance_of(Repositories::DestroyService) do |instance| + expect_next_instance_of(::Repositories::DestroyService) do |instance| expect(instance).to receive(:execute).and_call_original end diff --git a/spec/models/deployment_spec.rb b/spec/models/deployment_spec.rb index 0643e61147f..977100bf638 100644 --- a/spec/models/deployment_spec.rb +++ b/spec/models/deployment_spec.rb @@ -1611,7 +1611,7 @@ RSpec.describe Deployment, feature_category: :continuous_delivery do it 'removes deployment without any errors' do deployment = create(:deployment, environment: environment, project: project) - Repositories::DestroyService.new(project.repository).execute + ::Repositories::DestroyService.new(project.repository).execute project.save! # to trigger a repository removal expect { described_class.where(id: deployment).fast_destroy_all } diff --git a/spec/requests/api/graphql/mutations/projects/blobs_remove_spec.rb b/spec/requests/api/graphql/mutations/projects/blobs_remove_spec.rb index b5697f1022c..972fa4109d6 100644 --- a/spec/requests/api/graphql/mutations/projects/blobs_remove_spec.rb +++ b/spec/requests/api/graphql/mutations/projects/blobs_remove_spec.rb @@ -18,7 +18,7 @@ RSpec.describe "projectBlobsRemove", feature_category: :source_code_management d describe 'Removing blobs:' do it 'processes text redaction asynchoronously' do - expect(Repositories::RewriteHistoryWorker).to receive(:perform_async).with( + expect(::Repositories::RewriteHistoryWorker).to receive(:perform_async).with( project_id: project.id, user_id: current_user.id, blob_oids: blob_oids, redactions: [] ) diff --git a/spec/requests/api/graphql/mutations/projects/text_replace_spec.rb b/spec/requests/api/graphql/mutations/projects/text_replace_spec.rb index 016a5b746aa..1e699814dcd 100644 --- a/spec/requests/api/graphql/mutations/projects/text_replace_spec.rb +++ b/spec/requests/api/graphql/mutations/projects/text_replace_spec.rb @@ -32,7 +32,7 @@ RSpec.describe "projectTextReplace", feature_category: :source_code_management d describe 'Replacing text' do it 'processes text redaction asynchoronously' do - expect(Repositories::RewriteHistoryWorker).to receive(:perform_async).with( + expect(::Repositories::RewriteHistoryWorker).to receive(:perform_async).with( project_id: project.id, user_id: current_user.id, redactions: literal_replacements, blob_oids: [] ) diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index ec71058abbf..2bd24444206 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -5700,14 +5700,14 @@ RSpec.describe API::Projects, :aggregate_failures, feature_category: :groups_and end describe 'POST /projects/:id/housekeeping' do - let(:housekeeping) { Repositories::HousekeepingService.new(project) } + let(:housekeeping) { ::Repositories::HousekeepingService.new(project) } let(:params) { {} } let(:path) { "/projects/#{project.id}/housekeeping" } subject(:request) { post api(path, user), params: params } before do - allow(Repositories::HousekeepingService).to receive(:new).with(project, :eager).and_return(housekeeping) + allow(::Repositories::HousekeepingService).to receive(:new).with(project, :eager).and_return(housekeeping) end context 'when authenticated as owner' do @@ -5736,7 +5736,7 @@ RSpec.describe API::Projects, :aggregate_failures, feature_category: :groups_and let(:params) { { task: :prune } } it 'triggers a prune' do - expect(Repositories::HousekeepingService).to receive(:new).with(project, :prune).and_return(housekeeping) + expect(::Repositories::HousekeepingService).to receive(:new).with(project, :prune).and_return(housekeeping) expect(housekeeping).to receive(:execute).once request @@ -5749,7 +5749,7 @@ RSpec.describe API::Projects, :aggregate_failures, feature_category: :groups_and let(:params) { { task: :unsupported_task } } it 'responds with bad_request' do - expect(Repositories::HousekeepingService).not_to receive(:new) + expect(::Repositories::HousekeepingService).not_to receive(:new) request @@ -5759,7 +5759,7 @@ RSpec.describe API::Projects, :aggregate_failures, feature_category: :groups_and context 'when housekeeping lease is taken' do it 'returns conflict' do - expect(housekeeping).to receive(:execute).once.and_raise(Repositories::HousekeepingService::LeaseTaken) + expect(housekeeping).to receive(:execute).once.and_raise(::Repositories::HousekeepingService::LeaseTaken) request diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb index 26f31aa2a31..73781f24eb6 100644 --- a/spec/requests/api/repositories_spec.rb +++ b/spec/requests/api/repositories_spec.rb @@ -808,10 +808,10 @@ RSpec.describe API::Repositories, feature_category: :source_code_management do describe 'GET /projects/:id/repository/changelog' do it 'generates the changelog for a version' do - spy = instance_spy(Repositories::ChangelogService) + spy = instance_spy(::Repositories::ChangelogService) release_notes = 'Release notes' - allow(Repositories::ChangelogService) + allow(::Repositories::ChangelogService) .to receive(:new) .with( project, @@ -842,10 +842,10 @@ RSpec.describe API::Repositories, feature_category: :source_code_management do end it 'returns generated changelog when using JOB-TOKEN auth' do - spy = instance_spy(Repositories::ChangelogService) + spy = instance_spy(::Repositories::ChangelogService) release_notes = 'Release notes' - allow(Repositories::ChangelogService) + allow(::Repositories::ChangelogService) .to receive(:new) .with( project, @@ -877,9 +877,9 @@ RSpec.describe API::Repositories, feature_category: :source_code_management do end it 'supports leaving out the from and to attribute' do - spy = instance_spy(Repositories::ChangelogService) + spy = instance_spy(::Repositories::ChangelogService) - allow(Repositories::ChangelogService) + allow(::Repositories::ChangelogService) .to receive(:new) .with( project, @@ -906,9 +906,9 @@ RSpec.describe API::Repositories, feature_category: :source_code_management do end it 'supports specified config file path' do - spy = instance_spy(Repositories::ChangelogService) + spy = instance_spy(::Repositories::ChangelogService) - expect(Repositories::ChangelogService) + expect(::Repositories::ChangelogService) .to receive(:new) .with( project, @@ -962,9 +962,9 @@ RSpec.describe API::Repositories, feature_category: :source_code_management do describe 'POST /projects/:id/repository/changelog' do it 'generates the changelog for a version' do - spy = instance_spy(Repositories::ChangelogService) + spy = instance_spy(::Repositories::ChangelogService) - allow(Repositories::ChangelogService) + allow(::Repositories::ChangelogService) .to receive(:new) .with( project, @@ -1000,9 +1000,9 @@ RSpec.describe API::Repositories, feature_category: :source_code_management do end it 'supports leaving out the from and to attribute' do - spy = instance_spy(Repositories::ChangelogService) + spy = instance_spy(::Repositories::ChangelogService) - allow(Repositories::ChangelogService) + allow(::Repositories::ChangelogService) .to receive(:new) .with( project, @@ -1034,9 +1034,9 @@ RSpec.describe API::Repositories, feature_category: :source_code_management do end it 'produces an error when generating the changelog fails' do - spy = instance_spy(Repositories::ChangelogService) + spy = instance_spy(::Repositories::ChangelogService) - allow(Repositories::ChangelogService) + allow(::Repositories::ChangelogService) .to receive(:new) .with( project, @@ -1075,9 +1075,9 @@ RSpec.describe API::Repositories, feature_category: :source_code_management do end it "support specified config file path" do - spy = instance_spy(Repositories::ChangelogService) + spy = instance_spy(::Repositories::ChangelogService) - expect(Repositories::ChangelogService) + expect(::Repositories::ChangelogService) .to receive(:new) .with( project, diff --git a/spec/services/git/process_ref_changes_service_spec.rb b/spec/services/git/process_ref_changes_service_spec.rb index 56e1ba74c84..bdfafbb791e 100644 --- a/spec/services/git/process_ref_changes_service_spec.rb +++ b/spec/services/git/process_ref_changes_service_spec.rb @@ -201,10 +201,10 @@ RSpec.describe Git::ProcessRefChangesService, feature_category: :source_code_man end describe "housekeeping", :clean_gitlab_redis_cache, :clean_gitlab_redis_queues, :clean_gitlab_redis_shared_state do - let(:housekeeping) { Repositories::HousekeepingService.new(project) } + let(:housekeeping) { ::Repositories::HousekeepingService.new(project) } before do - allow(Repositories::HousekeepingService).to receive(:new).and_return(housekeeping) + allow(::Repositories::HousekeepingService).to receive(:new).and_return(housekeeping) allow(push_service_class) .to receive(:new) diff --git a/spec/services/git/wiki_push_service_spec.rb b/spec/services/git/wiki_push_service_spec.rb index d70b6d65625..2dd97e683c4 100644 --- a/spec/services/git/wiki_push_service_spec.rb +++ b/spec/services/git/wiki_push_service_spec.rb @@ -283,12 +283,12 @@ RSpec.describe Git::WikiPushService, :services, feature_category: :wiki do end describe '#perform_housekeeping', :clean_gitlab_redis_shared_state do - let(:housekeeping) { Repositories::HousekeepingService.new(wiki) } + let(:housekeeping) { ::Repositories::HousekeepingService.new(wiki) } subject { create_service(current_sha).execute } before do - allow(Repositories::HousekeepingService).to receive(:new).and_return(housekeeping) + allow(::Repositories::HousekeepingService).to receive(:new).and_return(housekeeping) end it 'does not perform housekeeping when not needed' do diff --git a/spec/services/merge_requests/cleanup_refs_service_spec.rb b/spec/services/merge_requests/cleanup_refs_service_spec.rb index 6edf165c204..a80a29b220a 100644 --- a/spec/services/merge_requests/cleanup_refs_service_spec.rb +++ b/spec/services/merge_requests/cleanup_refs_service_spec.rb @@ -110,7 +110,7 @@ RSpec.describe MergeRequests::CleanupRefsService, feature_category: :code_review context 'when repository no longer exists' do before do - Repositories::DestroyService.new(merge_request.project.repository).execute + ::Repositories::DestroyService.new(merge_request.project.repository).execute end it 'does not fail and still mark schedule as complete' do diff --git a/spec/services/projects/destroy_service_spec.rb b/spec/services/projects/destroy_service_spec.rb index cd961f46ba7..9ad3f92a3a3 100644 --- a/spec/services/projects/destroy_service_spec.rb +++ b/spec/services/projects/destroy_service_spec.rb @@ -331,7 +331,7 @@ RSpec.describe Projects::DestroyService, :aggregate_failures, :event_store_publi before do allow(project.repository).to receive(:before_delete).and_raise(::Gitlab::Git::CommandError) allow(Gitlab::GitLogger).to receive(:warn).with( - class: Repositories::DestroyService.name, + class: ::Repositories::DestroyService.name, container_id: project.id, disk_path: project.disk_path, message: 'Gitlab::Git::CommandError').and_call_original @@ -586,7 +586,7 @@ RSpec.describe Projects::DestroyService, :aggregate_failures, :event_store_publi # 3. Design repository it 'Repositories::DestroyService is called for existing repos' do - expect_next_instances_of(Repositories::DestroyService, 3) do |instance| + expect_next_instances_of(::Repositories::DestroyService, 3) do |instance| expect(instance).to receive(:execute).and_return(status: :success) end @@ -596,7 +596,7 @@ RSpec.describe Projects::DestroyService, :aggregate_failures, :event_store_publi context 'when the removal has errors' do using RSpec::Parameterized::TableSyntax - let(:mock_error) { instance_double(Repositories::DestroyService, execute: { message: 'foo', status: :error }) } + let(:mock_error) { instance_double(::Repositories::DestroyService, execute: { message: 'foo', status: :error }) } let(:project_repository) { project.repository } let(:wiki_repository) { project.wiki.repository } let(:design_repository) { project.design_repository } @@ -609,8 +609,8 @@ RSpec.describe Projects::DestroyService, :aggregate_failures, :event_store_publi with_them do before do - allow(Repositories::DestroyService).to receive(:new).with(anything).and_call_original - allow(Repositories::DestroyService).to receive(:new).with(repo).and_return(mock_error) + allow(::Repositories::DestroyService).to receive(:new).with(anything).and_call_original + allow(::Repositories::DestroyService).to receive(:new).with(repo).and_return(mock_error) end it 'raises correct error' do diff --git a/spec/services/projects/update_repository_storage_service_spec.rb b/spec/services/projects/update_repository_storage_service_spec.rb index 9602edcfa86..719fbf556f2 100644 --- a/spec/services/projects/update_repository_storage_service_spec.rb +++ b/spec/services/projects/update_repository_storage_service_spec.rb @@ -170,7 +170,7 @@ RSpec.describe Projects::UpdateRepositoryStorageService, feature_category: :sour expect do subject.execute - end.to raise_error(Repositories::ReplicateService::Error, /Failed to verify project repository checksum/) + end.to raise_error(::Repositories::ReplicateService::Error, /Failed to verify project repository checksum/) expect(project).not_to be_repository_read_only expect(project.repository_storage).to eq(storage_source) @@ -361,7 +361,7 @@ RSpec.describe Projects::UpdateRepositoryStorageService, feature_category: :sour expect do subject.execute - end.to raise_error(Repositories::ReplicateService::Error, /Failed to verify object_pool repository/) + end.to raise_error(::Repositories::ReplicateService::Error, /Failed to verify object_pool repository/) project.reload diff --git a/spec/services/repositories/changelog_service_spec.rb b/spec/services/repositories/changelog_service_spec.rb index 77df0b5921d..908e61d6b82 100644 --- a/spec/services/repositories/changelog_service_spec.rb +++ b/spec/services/repositories/changelog_service_spec.rb @@ -226,10 +226,10 @@ RSpec.describe Repositories::ChangelogService, feature_category: :source_code_ma service = described_class .new(project, user, version: '1.0.0', to: 'bar') - finder_spy = instance_spy(Repositories::ChangelogTagFinder) + finder_spy = instance_spy(::Repositories::ChangelogTagFinder) tag = double(:tag, target_commit: double(:commit, id: '123')) - allow(Repositories::ChangelogTagFinder) + allow(::Repositories::ChangelogTagFinder) .to receive(:new) .with(project, regex: an_instance_of(String)) .and_return(finder_spy) @@ -246,9 +246,9 @@ RSpec.describe Repositories::ChangelogService, feature_category: :source_code_ma service = described_class .new(project, user, version: '1.0.0', to: 'bar') - finder_spy = instance_spy(Repositories::ChangelogTagFinder) + finder_spy = instance_spy(::Repositories::ChangelogTagFinder) - allow(Repositories::ChangelogTagFinder) + allow(::Repositories::ChangelogTagFinder) .to receive(:new) .with(project, regex: an_instance_of(String)) .and_return(finder_spy) diff --git a/spec/services/repositories/rewrite_history_service_spec.rb b/spec/services/repositories/rewrite_history_service_spec.rb index 3c2a5929013..29cc903d4b5 100644 --- a/spec/services/repositories/rewrite_history_service_spec.rb +++ b/spec/services/repositories/rewrite_history_service_spec.rb @@ -156,7 +156,7 @@ RSpec.describe Repositories::RewriteHistoryService, feature_category: :source_co let(:redactions) { ['p455w0rd'] } it 'triggers a RewriteHistoryWorker job' do - expect(Repositories::RewriteHistoryWorker).to receive(:perform_async).with( + expect(::Repositories::RewriteHistoryWorker).to receive(:perform_async).with( project_id: project.id, user_id: user.id, blob_oids: blob_oids, redactions: redactions ) diff --git a/spec/services/snippets/bulk_destroy_service_spec.rb b/spec/services/snippets/bulk_destroy_service_spec.rb index 208386aee48..2d74fc4beab 100644 --- a/spec/services/snippets/bulk_destroy_service_spec.rb +++ b/spec/services/snippets/bulk_destroy_service_spec.rb @@ -22,8 +22,8 @@ RSpec.describe Snippets::BulkDestroyService, feature_category: :source_code_mana it 'deletes the snippets in bulk' do response = nil - expect(Repositories::DestroyService).to receive(:new).with(personal_snippet.repository).and_call_original - expect(Repositories::DestroyService).to receive(:new).with(project_snippet.repository).and_call_original + expect(::Repositories::DestroyService).to receive(:new).with(personal_snippet.repository).and_call_original + expect(::Repositories::DestroyService).to receive(:new).with(project_snippet.repository).and_call_original aggregate_failures do expect do @@ -86,7 +86,7 @@ RSpec.describe Snippets::BulkDestroyService, feature_category: :source_code_mana context 'when an error is raised deleting the repository' do before do - allow_next_instance_of(Repositories::DestroyService) do |instance| + allow_next_instance_of(::Repositories::DestroyService) do |instance| allow(instance).to receive(:execute).and_return({ status: :error }) end end @@ -112,9 +112,9 @@ RSpec.describe Snippets::BulkDestroyService, feature_category: :source_code_mana it 'returns success' do response = nil - expect(Repositories::DestroyService).to receive(:new).with(personal_snippet.repository).and_call_original - expect(Repositories::DestroyService).to receive(:new).with(project_snippet.repository).and_call_original - expect(Repositories::DestroyService).to receive(:new).with(snippet_without_repo.repository).and_call_original + expect(::Repositories::DestroyService).to receive(:new).with(personal_snippet.repository).and_call_original + expect(::Repositories::DestroyService).to receive(:new).with(project_snippet.repository).and_call_original + expect(::Repositories::DestroyService).to receive(:new).with(snippet_without_repo.repository).and_call_original expect do response = subject.execute diff --git a/spec/services/snippets/destroy_service_spec.rb b/spec/services/snippets/destroy_service_spec.rb index 29898e3ab09..8461509ca98 100644 --- a/spec/services/snippets/destroy_service_spec.rb +++ b/spec/services/snippets/destroy_service_spec.rb @@ -41,7 +41,7 @@ RSpec.describe Snippets::DestroyService, feature_category: :source_code_manageme shared_examples 'deletes the snippet repository' do it 'removes the snippet repository' do expect(snippet.repository.exists?).to be_truthy - expect_next_instance_of(Repositories::DestroyService) do |instance| + expect_next_instance_of(::Repositories::DestroyService) do |instance| expect(instance).to receive(:execute).and_call_original end @@ -50,7 +50,7 @@ RSpec.describe Snippets::DestroyService, feature_category: :source_code_manageme context 'when the repository deletion service raises an error' do before do - allow_next_instance_of(Repositories::DestroyService) do |instance| + allow_next_instance_of(::Repositories::DestroyService) do |instance| allow(instance).to receive(:execute).and_return({ status: :error }) end end @@ -70,7 +70,7 @@ RSpec.describe Snippets::DestroyService, feature_category: :source_code_manageme it 'does not schedule anything and return success' do allow(snippet).to receive(:repository).and_return(nil) - expect_next_instance_of(Repositories::DestroyService) do |instance| + expect_next_instance_of(::Repositories::DestroyService) do |instance| expect(instance).to receive(:execute).and_call_original end @@ -150,7 +150,7 @@ RSpec.describe Snippets::DestroyService, feature_category: :source_code_manageme expect(snippet.repository).not_to be_nil expect(snippet.repository.exists?).to be_falsey - expect_next_instance_of(Repositories::DestroyService) do |instance| + expect_next_instance_of(::Repositories::DestroyService) do |instance| expect(instance).to receive(:execute).and_call_original end diff --git a/spec/services/snippets/update_repository_storage_service_spec.rb b/spec/services/snippets/update_repository_storage_service_spec.rb index 67a2604475c..72c5df0cc66 100644 --- a/spec/services/snippets/update_repository_storage_service_spec.rb +++ b/spec/services/snippets/update_repository_storage_service_spec.rb @@ -109,7 +109,7 @@ RSpec.describe Snippets::UpdateRepositoryStorageService, feature_category: :sour expect do subject.execute - end.to raise_error(Repositories::ReplicateService::Error, /Failed to verify snippet repository checksum from \w+ to not matching checksum/) + end.to raise_error(::Repositories::ReplicateService::Error, /Failed to verify snippet repository checksum from \w+ to not matching checksum/) expect(snippet).not_to be_repository_read_only expect(snippet.repository_storage).to eq('default') diff --git a/spec/support/shared_examples/models/concerns/has_repository_shared_examples.rb b/spec/support/shared_examples/models/concerns/has_repository_shared_examples.rb index 187c0b3ab43..a127451fdb6 100644 --- a/spec/support/shared_examples/models/concerns/has_repository_shared_examples.rb +++ b/spec/support/shared_examples/models/concerns/has_repository_shared_examples.rb @@ -162,7 +162,7 @@ RSpec.shared_examples 'model with repository' do end describe '#after_repository_change_head' do - let(:event) { instance_double('Repositories::DefaultBranchChangedEvent') } + let(:event) { instance_double('::Repositories::DefaultBranchChangedEvent') } let(:event_data) { { container_id: stubbed_container.id, container_type: stubbed_container.class.name } } it 'calls #reload_default_branch' do @@ -172,7 +172,7 @@ RSpec.shared_examples 'model with repository' do end it 'publishes an Repositories::DefaultBranchChangedEvent event' do - allow(Repositories::DefaultBranchChangedEvent) + allow(::Repositories::DefaultBranchChangedEvent) .to receive(:new) .with(data: event_data) .and_return(event) diff --git a/spec/support/shared_examples/requests/lfs_http_shared_examples.rb b/spec/support/shared_examples/requests/lfs_http_shared_examples.rb index 83be0cc1fe3..ad1722778f4 100644 --- a/spec/support/shared_examples/requests/lfs_http_shared_examples.rb +++ b/spec/support/shared_examples/requests/lfs_http_shared_examples.rb @@ -9,7 +9,7 @@ end RSpec.shared_examples 'LFS http 200 blob response' do it_behaves_like 'LFS http expected response code and message' do let(:response_code) { :ok } - let(:content_type) { Repositories::LfsApiController::LFS_TRANSFER_CONTENT_TYPE } + let(:content_type) { ::Repositories::LfsApiController::LFS_TRANSFER_CONTENT_TYPE } let(:response_headers) { { 'X-Sendfile' => lfs_object.file.path } } end end diff --git a/spec/support/shared_examples/services/projects/update_repository_storage_service_shared_examples.rb b/spec/support/shared_examples/services/projects/update_repository_storage_service_shared_examples.rb index f3fadd3a1eb..c6a6fdd03f8 100644 --- a/spec/support/shared_examples/services/projects/update_repository_storage_service_shared_examples.rb +++ b/spec/support/shared_examples/services/projects/update_repository_storage_service_shared_examples.rb @@ -139,7 +139,7 @@ RSpec.shared_examples 'moves repository to another storage' do |repository_type| expect do subject.execute - end.to raise_error(Repositories::ReplicateService::Error, /Failed to verify \w+ repository checksum from \w+ to not matching checksum/) + end.to raise_error(::Repositories::ReplicateService::Error, /Failed to verify \w+ repository checksum from \w+ to not matching checksum/) expect(project).not_to be_repository_read_only expect(project.repository_storage).to eq('default') diff --git a/spec/support/shared_examples/services/repositories/housekeeping_shared_examples.rb b/spec/support/shared_examples/services/repositories/housekeeping_shared_examples.rb index 8cc71230ba4..0937aef6419 100644 --- a/spec/support/shared_examples/services/repositories/housekeeping_shared_examples.rb +++ b/spec/support/shared_examples/services/repositories/housekeeping_shared_examples.rb @@ -40,19 +40,19 @@ RSpec.shared_examples 'housekeeps repository' do it 'does not enqueue a job' do expect(resource.git_garbage_collect_worker_klass).not_to receive(:perform_async) - expect { subject.execute }.to raise_error(Repositories::HousekeepingService::LeaseTaken) + expect { subject.execute }.to raise_error(::Repositories::HousekeepingService::LeaseTaken) end it 'does not reset pushes_since_gc' do expect do - expect { subject.execute }.to raise_error(Repositories::HousekeepingService::LeaseTaken) + expect { subject.execute }.to raise_error(::Repositories::HousekeepingService::LeaseTaken) end.not_to change { resource.pushes_since_gc } end it 'does not yield' do expect do |block| expect { subject.execute(&block) } - .to raise_error(Repositories::HousekeepingService::LeaseTaken) + .to raise_error(::Repositories::HousekeepingService::LeaseTaken) end.not_to yield_with_no_args end end diff --git a/spec/workers/projects/after_import_worker_spec.rb b/spec/workers/projects/after_import_worker_spec.rb index f9133ceb774..f7f75c5c3c6 100644 --- a/spec/workers/projects/after_import_worker_spec.rb +++ b/spec/workers/projects/after_import_worker_spec.rb @@ -13,7 +13,7 @@ RSpec.describe Projects::AfterImportWorker, feature_category: :importers do describe '#execute' do before do - allow(Repositories::HousekeepingService) + allow(::Repositories::HousekeepingService) .to receive(:new).with(project).and_return(housekeeping_service) allow(housekeeping_service) @@ -71,10 +71,10 @@ RSpec.describe Projects::AfterImportWorker, feature_category: :importers do end context 'when housekeeping service lease is taken' do - let(:exception) { Repositories::HousekeepingService::LeaseTaken.new } + let(:exception) { ::Repositories::HousekeepingService::LeaseTaken.new } it 'logs the error message' do - allow_next_instance_of(Repositories::HousekeepingService) do |instance| + allow_next_instance_of(::Repositories::HousekeepingService) do |instance| expect(instance).to receive(:execute).and_raise(exception) end diff --git a/spec/workers/repositories/rewrite_history_worker_spec.rb b/spec/workers/repositories/rewrite_history_worker_spec.rb index 4f36b5da101..d8dc4e9019d 100644 --- a/spec/workers/repositories/rewrite_history_worker_spec.rb +++ b/spec/workers/repositories/rewrite_history_worker_spec.rb @@ -23,7 +23,7 @@ RSpec.describe Repositories::RewriteHistoryWorker, feature_category: :source_cod end it 'executes RewriteHistoryService service' do - allow_next_instance_of(Repositories::RewriteHistoryService) do |instance| + allow_next_instance_of(::Repositories::RewriteHistoryService) do |instance| expect(instance).to receive(:execute).with(blob_oids: blob_oids, redactions: []).and_call_original end @@ -34,7 +34,7 @@ RSpec.describe Repositories::RewriteHistoryWorker, feature_category: :source_cod let(:project_id) { non_existing_record_id } it 'skips the execution' do - expect(Repositories::RewriteHistoryService).not_to receive(:new) + expect(::Repositories::RewriteHistoryService).not_to receive(:new) perform end end @@ -43,14 +43,14 @@ RSpec.describe Repositories::RewriteHistoryWorker, feature_category: :source_cod let(:user_id) { non_existing_record_id } it 'skips the execution' do - expect(Repositories::RewriteHistoryService).not_to receive(:new) + expect(::Repositories::RewriteHistoryService).not_to receive(:new) perform end end describe 'Emails' do before do - allow_next_instance_of(Repositories::RewriteHistoryService) do |instance| + allow_next_instance_of(::Repositories::RewriteHistoryService) do |instance| allow(instance).to receive(:execute).and_return(response) end end