Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
2a3be6ad50
commit
647f13ebef
|
|
@ -1680,6 +1680,8 @@
|
|||
when: never
|
||||
- <<: *if-security-merge-request
|
||||
when: never
|
||||
- <<: *if-merge-request-targeting-stable-branch
|
||||
when: never
|
||||
- !reference [.frontend:rules:jest, rules]
|
||||
|
||||
################
|
||||
|
|
|
|||
|
|
@ -1932,7 +1932,6 @@ Layout/LineLength:
|
|||
- 'lib/api/rubygem_packages.rb'
|
||||
- 'lib/api/settings.rb'
|
||||
- 'lib/api/snippet_repository_storage_moves.rb'
|
||||
- 'lib/api/snippets.rb'
|
||||
- 'lib/api/submodules.rb'
|
||||
- 'lib/api/suggestions.rb'
|
||||
- 'lib/api/tags.rb'
|
||||
|
|
|
|||
|
|
@ -244,7 +244,7 @@ export default {
|
|||
placement="bottom-end"
|
||||
class="submit-review-dropdown"
|
||||
:class="{ 'submit-review-dropdown-animated': shouldAnimateReviewButton }"
|
||||
data-testid="submit-review-dropdown"
|
||||
data-testid="review-drawer-toggle"
|
||||
fluid-width
|
||||
@beforeClose="onBeforeClose"
|
||||
@shown="setDropdownVisible(true)"
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ export default {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="draftsCount > 0 || isReviewer">
|
||||
<div v-if="draftsCount > 0 || isReviewer" data-testid="review-drawer-toggle">
|
||||
<gl-button variant="confirm" data-testid="review-drawer-toggle" @click="setDrawerOpened(true)">
|
||||
{{ __('Your review') }}
|
||||
<drafts-count
|
||||
|
|
|
|||
|
|
@ -61,6 +61,6 @@ export default {
|
|||
v-on="$listeners"
|
||||
>
|
||||
<file-row-stats v-if="showFileRowStats" :file="file" class="gl-mr-2" />
|
||||
<changed-file-icon :file="file" :size="16" :show-tooltip="true" />
|
||||
<changed-file-icon :file="file" :size="16" :show-tooltip="true" :as-button="false" />
|
||||
</file-row>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -230,12 +230,26 @@ export default {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div class="tree-list-holder gl-flex gl-flex-col" data-testid="file-tree-container">
|
||||
<section
|
||||
class="tree-list-holder gl-flex gl-flex-col"
|
||||
data-testid="file-tree-container"
|
||||
aria-labelledby="tree-list-title"
|
||||
>
|
||||
<div class="gl-mb-3 gl-flex gl-items-center">
|
||||
<h5 class="gl-my-0 gl-inline-block">{{ __('Files') }}</h5>
|
||||
<gl-badge v-if="totalFilesCount != null" class="gl-ml-2" data-testid="file-count">{{
|
||||
totalFilesCount
|
||||
}}</gl-badge>
|
||||
<h2
|
||||
id="tree-list-title"
|
||||
class="gl-my-0 gl-inline-block gl-text-base"
|
||||
:aria-label="__('File browser')"
|
||||
>
|
||||
{{ __('Files') }}
|
||||
</h2>
|
||||
<gl-badge
|
||||
v-if="totalFilesCount != null"
|
||||
class="gl-ml-2"
|
||||
data-testid="file-count"
|
||||
aria-hidden="true"
|
||||
>{{ totalFilesCount }}</gl-badge
|
||||
>
|
||||
<gl-button-group class="gl-ml-auto">
|
||||
<gl-button
|
||||
v-gl-tooltip.hover
|
||||
|
|
@ -257,7 +271,6 @@ export default {
|
|||
/>
|
||||
</gl-button-group>
|
||||
</div>
|
||||
<label for="diff-tree-search" class="sr-only">{{ $options.searchPlaceholder }}</label>
|
||||
<gl-search-box-by-type
|
||||
id="diff-tree-search"
|
||||
v-model="search"
|
||||
|
|
@ -267,7 +280,11 @@ export default {
|
|||
:clear-button-title="__('Clear search')"
|
||||
class="gl-mb-3"
|
||||
/>
|
||||
<div :class="{ 'tree-list-blobs': !renderTreeList || search }" class="mr-tree-list">
|
||||
<nav
|
||||
:class="{ 'tree-list-blobs': !renderTreeList || search }"
|
||||
class="mr-tree-list"
|
||||
:aria-label="__('File tree')"
|
||||
>
|
||||
<recycle-scroller
|
||||
v-if="treeList.length"
|
||||
ref="scroller"
|
||||
|
|
@ -286,7 +303,7 @@ export default {
|
|||
:style="{ '--level': item.level }"
|
||||
:class="{ 'tree-list-parent': item.level > 0 }"
|
||||
:tabindex="item.loading ? -1 : 0"
|
||||
class="gl-relative !gl-m-1"
|
||||
class="gl-relative"
|
||||
:data-file-row="item.fileHash"
|
||||
@toggleTreeOpen="$emit('toggleFolder', $event)"
|
||||
@clickFile="!item.loading && $emit('clickFile', $event)"
|
||||
|
|
@ -299,8 +316,8 @@ export default {
|
|||
<p v-else class="prepend-top-20 append-bottom-20 text-center">
|
||||
{{ s__('MergeRequest|No files found') }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ fragment Group on Group {
|
|||
id
|
||||
}
|
||||
webUrl
|
||||
organizationEditPath
|
||||
descriptionHtml
|
||||
avatarUrl
|
||||
descendantGroupsCount
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
#import "~/organizations/shared/graphql/fragments/group.fragment.graphql"
|
||||
#import "~/graphql_shared/fragments/group.fragment.graphql"
|
||||
|
||||
query getMemberYourWorkGroups($search: String, $sort: String, $parentId: Int, $page: Int) {
|
||||
groups(search: $search, sort: $sort, parentId: $parentId, page: $page) @client {
|
||||
|
|
|
|||
|
|
@ -36,7 +36,4 @@ export const formatGroupForGraphQLResolver = (group) => ({
|
|||
projectsCount: group.project_count,
|
||||
children: group.children?.length ? group.children.map(formatGroupForGraphQLResolver) : [],
|
||||
childrenCount: group.subgroup_count,
|
||||
// Properties below are hard coded for now until API has been
|
||||
// updated to support these fields.
|
||||
organizationEditPath: '',
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#import "~/graphql_shared/fragments/page_info.fragment.graphql"
|
||||
#import "~/organizations/shared/graphql/fragments/group.fragment.graphql"
|
||||
#import "~/graphql_shared/fragments/group.fragment.graphql"
|
||||
|
||||
query getOrganizationGroups(
|
||||
$id: OrganizationsOrganizationID!
|
||||
|
|
@ -22,6 +22,7 @@ query getOrganizationGroups(
|
|||
) {
|
||||
nodes {
|
||||
...Group
|
||||
organizationEditPath
|
||||
}
|
||||
pageInfo {
|
||||
...PageInfo
|
||||
|
|
|
|||
|
|
@ -297,13 +297,6 @@ export default {
|
|||
:show-cleanup-policy-link="config.showCleanupPolicyLink"
|
||||
>
|
||||
<template #commands>
|
||||
<cli-commands
|
||||
v-if="showCommands"
|
||||
:docker-build-command="dockerBuildCommand"
|
||||
:docker-push-command="dockerPushCommand"
|
||||
:docker-login-command="dockerLoginCommand"
|
||||
class="!gl-w-auto"
|
||||
/>
|
||||
<gl-button
|
||||
v-if="config.showContainerRegistrySettings"
|
||||
v-gl-tooltip="$options.i18n.SETTINGS_TEXT"
|
||||
|
|
@ -312,6 +305,13 @@ export default {
|
|||
:href="config.settingsPath"
|
||||
:aria-label="$options.i18n.SETTINGS_TEXT"
|
||||
/>
|
||||
<cli-commands
|
||||
v-if="showCommands"
|
||||
:docker-build-command="dockerBuildCommand"
|
||||
:docker-push-command="dockerPushCommand"
|
||||
:docker-login-command="dockerLoginCommand"
|
||||
class="!gl-w-auto"
|
||||
/>
|
||||
</template>
|
||||
</registry-header>
|
||||
<persisted-search
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ export default {
|
|||
settingBlockDescription: s__(
|
||||
'ContainerRegistry|When a container repository is protected, only users with specific roles can push and delete container images. This helps prevent unauthorized modifications.',
|
||||
),
|
||||
protectionRuleDeletionConfirmModal: {
|
||||
deletionConfirmModal: {
|
||||
title: s__('ContainerRegistry|Delete container repository protection rule?'),
|
||||
descriptionWarning: s__(
|
||||
'ContainerRegistry|You are about to delete the container repository protection rule for %{repositoryPathPattern}.',
|
||||
|
|
@ -162,7 +162,7 @@ export default {
|
|||
last: PAGINATION_DEFAULT_PER_PAGE,
|
||||
};
|
||||
},
|
||||
showProtectionRuleDeletionConfirmModal(protectionRule) {
|
||||
showDeletionConfirmModal(protectionRule) {
|
||||
this.protectionRuleMutationItem = protectionRule;
|
||||
},
|
||||
clearAlertMessage() {
|
||||
|
|
@ -172,10 +172,10 @@ export default {
|
|||
this.protectionRuleMutationItem = null;
|
||||
this.protectionRuleMutationInProgress = false;
|
||||
},
|
||||
isProtectionRuleMinimumAccessLevelForPushFormSelectDisabled(item) {
|
||||
isMinimumAccessLevelForPushDisabled(item) {
|
||||
return this.isProtectionRuleMutationInProgress(item);
|
||||
},
|
||||
isProtectionRuleDeleteButtonDisabled(item) {
|
||||
isDeleteActionDisabled(item) {
|
||||
return this.isProtectionRuleMutationInProgress(item);
|
||||
},
|
||||
isProtectionRuleMutationInProgress(item) {
|
||||
|
|
@ -207,12 +207,12 @@ export default {
|
|||
this.resetProtectionRuleMutation();
|
||||
});
|
||||
},
|
||||
updateProtectionRuleMinimumAccessLevelForPush(protectionRule) {
|
||||
updateMinimumAccessLevelForPush(protectionRule) {
|
||||
this.updateProtectionRule(protectionRule, {
|
||||
minimumAccessLevelForPush: protectionRule.minimumAccessLevelForPush || null,
|
||||
});
|
||||
},
|
||||
updateProtectionRuleMinimumAccessLevelForDelete(protectionRule) {
|
||||
updateMinimumAccessLevelForDelete(protectionRule) {
|
||||
this.updateProtectionRule(protectionRule, {
|
||||
minimumAccessLevelForDelete: protectionRule.minimumAccessLevelForDelete || null,
|
||||
});
|
||||
|
|
@ -334,9 +334,9 @@ export default {
|
|||
required
|
||||
:aria-label="$options.i18n.minimumAccessLevelForPush"
|
||||
:options="containerRepositoryMinimumAccessLevelOptions"
|
||||
:disabled="isProtectionRuleMinimumAccessLevelForPushFormSelectDisabled(item)"
|
||||
:disabled="isMinimumAccessLevelForPushDisabled(item)"
|
||||
data-testid="minimum-access-level-for-push-select"
|
||||
@change="updateProtectionRuleMinimumAccessLevelForPush(item)"
|
||||
@change="updateMinimumAccessLevelForPush(item)"
|
||||
/>
|
||||
</template>
|
||||
|
||||
|
|
@ -348,8 +348,8 @@ export default {
|
|||
:aria-label="$options.i18n.minimumAccessLevelForDelete"
|
||||
:options="containerRepositoryMinimumAccessLevelOptions"
|
||||
data-testid="minimum-access-level-for-delete-select"
|
||||
:disabled="isProtectionRuleMinimumAccessLevelForPushFormSelectDisabled(item)"
|
||||
@change="updateProtectionRuleMinimumAccessLevelForDelete(item)"
|
||||
:disabled="isMinimumAccessLevelForPushDisabled(item)"
|
||||
@change="updateMinimumAccessLevelForDelete(item)"
|
||||
/>
|
||||
</template>
|
||||
|
||||
|
|
@ -361,9 +361,9 @@ export default {
|
|||
icon="remove"
|
||||
:title="__('Delete')"
|
||||
:aria-label="__('Delete')"
|
||||
:disabled="isProtectionRuleDeleteButtonDisabled(item)"
|
||||
:disabled="isDeleteActionDisabled(item)"
|
||||
data-testid="delete-btn"
|
||||
@click="showProtectionRuleDeletionConfirmModal(item)"
|
||||
@click="showDeletionConfirmModal(item)"
|
||||
/>
|
||||
</template>
|
||||
</gl-table>
|
||||
|
|
@ -386,19 +386,19 @@ export default {
|
|||
v-if="protectionRuleMutationItem"
|
||||
:modal-id="$options.modal.id"
|
||||
size="sm"
|
||||
:title="$options.i18n.protectionRuleDeletionConfirmModal.title"
|
||||
:title="$options.i18n.deletionConfirmModal.title"
|
||||
:action-primary="$options.modalActionPrimary"
|
||||
:action-cancel="$options.modalActionCancel"
|
||||
@primary="deleteProtectionRule(protectionRuleMutationItem)"
|
||||
>
|
||||
<p>
|
||||
<gl-sprintf :message="$options.i18n.protectionRuleDeletionConfirmModal.descriptionWarning">
|
||||
<gl-sprintf :message="$options.i18n.deletionConfirmModal.descriptionWarning">
|
||||
<template #repositoryPathPattern>
|
||||
<strong>{{ protectionRuleMutationItem.repositoryPathPattern }}</strong>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</p>
|
||||
<p>{{ $options.i18n.protectionRuleDeletionConfirmModal.descriptionConsequence }}</p>
|
||||
<p>{{ $options.i18n.deletionConfirmModal.descriptionConsequence }}</p>
|
||||
</gl-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ export default {
|
|||
this.protectionRuleMutationItem = null;
|
||||
this.protectionRuleMutationInProgress = false;
|
||||
},
|
||||
showProtectionRuleDeletionConfirmModal(protectionRule) {
|
||||
showDeletionConfirmModal(protectionRule) {
|
||||
this.protectionRuleMutationItem = protectionRule;
|
||||
this.showModal = true;
|
||||
},
|
||||
|
|
@ -233,7 +233,7 @@ export default {
|
|||
deleteIconButton: __('Delete'),
|
||||
editIconButton: __('Edit'),
|
||||
title: s__('ContainerRegistry|Protected container image tags'),
|
||||
protectionRuleDeletionConfirmModal: {
|
||||
deletionConfirmModal: {
|
||||
title: s__('ContainerRegistry|Delete protection rule'),
|
||||
description: s__(
|
||||
'ContainerRegistry|Are you sure you want to delete the protected container tags rule %{tagNamePattern}?',
|
||||
|
|
@ -359,7 +359,7 @@ export default {
|
|||
icon="remove"
|
||||
:title="$options.i18n.deleteIconButton"
|
||||
:aria-label="$options.i18n.deleteIconButton"
|
||||
@click="showProtectionRuleDeletionConfirmModal(item)"
|
||||
@click="showDeletionConfirmModal(item)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -387,13 +387,13 @@ export default {
|
|||
v-model="showModal"
|
||||
:modal-id="$options.modal.id"
|
||||
size="sm"
|
||||
:title="$options.i18n.protectionRuleDeletionConfirmModal.title"
|
||||
:title="$options.i18n.deletionConfirmModal.title"
|
||||
:action-primary="$options.modalActionPrimary"
|
||||
:action-cancel="$options.modalActionCancel"
|
||||
@primary="deleteProtectionRule(protectionRuleMutationItem)"
|
||||
>
|
||||
<p>
|
||||
<gl-sprintf :message="$options.i18n.protectionRuleDeletionConfirmModal.description">
|
||||
<gl-sprintf :message="$options.i18n.deletionConfirmModal.description">
|
||||
<template #tagNamePattern>
|
||||
<strong>{{ mutationItemTagNamePattern }}</strong>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import {
|
|||
GlSprintf,
|
||||
} from '@gitlab/ui';
|
||||
import CrudComponent from '~/vue_shared/components/crud_component.vue';
|
||||
import packagesProtectionRuleQuery from '~/packages_and_registries/settings/project/graphql/queries/get_packages_protection_rules.query.graphql';
|
||||
import getPackagesProtectionRuleQuery from '~/packages_and_registries/settings/project/graphql/queries/get_packages_protection_rules.query.graphql';
|
||||
import { getPackageTypeLabel } from '~/packages_and_registries/package_registry/utils';
|
||||
import deletePackagesProtectionRuleMutation from '~/packages_and_registries/settings/project/graphql/mutations/delete_packages_protection_rule.mutation.graphql';
|
||||
import PackagesProtectionRuleForm from '~/packages_and_registries/settings/project/components/packages_protection_rule_form.vue';
|
||||
|
|
@ -55,8 +55,7 @@ export default {
|
|||
settingBlockDescription: s__(
|
||||
'PackageRegistry|When a package is protected, only certain user roles can push, update, and delete the protected package, which helps to avoid tampering with the package.',
|
||||
),
|
||||
createProtectionRuleText: s__('PackageRegistry|Add protection rule'),
|
||||
protectionRuleDeletionConfirmModal: {
|
||||
deletionConfirmModal: {
|
||||
title: s__('PackageRegistry|Delete package protection rule?'),
|
||||
descriptionWarning: s__(
|
||||
'PackageRegistry|You are about to delete the package protection rule for %{packageNamePattern}.',
|
||||
|
|
@ -68,23 +67,43 @@ export default {
|
|||
minimumAccessLevelForPush: I18N_MINIMUM_ACCESS_LEVEL_FOR_PUSH,
|
||||
minimumAccessLevelForDelete: I18N_MINIMUM_ACCESS_LEVEL_FOR_DELETE,
|
||||
},
|
||||
apollo: {
|
||||
protectionRulesQueryPayload: {
|
||||
query: getPackagesProtectionRuleQuery,
|
||||
context: {
|
||||
batchKey: 'PackageRegistryProjectSettings',
|
||||
},
|
||||
variables() {
|
||||
return {
|
||||
projectPath: this.projectPath,
|
||||
...this.protectionRulesQueryPaginationParams,
|
||||
};
|
||||
},
|
||||
update(data) {
|
||||
return data.project?.packagesProtectionRules ?? this.protectionRulesQueryPayload;
|
||||
},
|
||||
error(e) {
|
||||
this.alertErrorMessage = e.message;
|
||||
},
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
packageProtectionRules: [],
|
||||
packageProtectionRulesQueryPayload: { nodes: [], pageInfo: {} },
|
||||
packageProtectionRulesQueryPaginationParams: { first: PAGINATION_DEFAULT_PER_PAGE },
|
||||
protectionRuleMutationInProgress: false,
|
||||
protectionRuleMutationItem: null,
|
||||
protectionRules: [],
|
||||
protectionRulesQueryPayload: { nodes: [], pageInfo: {} },
|
||||
protectionRulesQueryPaginationParams: { first: PAGINATION_DEFAULT_PER_PAGE },
|
||||
mutationInProgress: false,
|
||||
mutationItem: null,
|
||||
alertErrorMessage: '',
|
||||
showDrawer: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
containsTableItems() {
|
||||
return this.packageProtectionRulesQueryResult.length > 0;
|
||||
return this.protectionRulesQueryResult.length > 0;
|
||||
},
|
||||
drawerTitle() {
|
||||
return this.protectionRuleMutationItem
|
||||
return this.mutationItem
|
||||
? s__('PackageRegistry|Edit protection rule')
|
||||
: s__('PackageRegistry|Add protection rule');
|
||||
},
|
||||
|
|
@ -94,70 +113,50 @@ export default {
|
|||
: this.$options.fields.filter((field) => field.key !== 'minimumAccessLevelForDelete');
|
||||
},
|
||||
tableItems() {
|
||||
return this.packageProtectionRulesQueryResult.map((packagesProtectionRule) => {
|
||||
return this.protectionRulesQueryResult.map((protectionRule) => {
|
||||
return {
|
||||
id: packagesProtectionRule.id,
|
||||
minimumAccessLevelForDelete: packagesProtectionRule.minimumAccessLevelForDelete,
|
||||
minimumAccessLevelForPush: packagesProtectionRule.minimumAccessLevelForPush,
|
||||
packageNamePattern: packagesProtectionRule.packageNamePattern,
|
||||
packageType: packagesProtectionRule.packageType,
|
||||
id: protectionRule.id,
|
||||
minimumAccessLevelForDelete: protectionRule.minimumAccessLevelForDelete,
|
||||
minimumAccessLevelForPush: protectionRule.minimumAccessLevelForPush,
|
||||
packageNamePattern: protectionRule.packageNamePattern,
|
||||
packageType: protectionRule.packageType,
|
||||
};
|
||||
});
|
||||
},
|
||||
packageProtectionRulesQueryPageInfo() {
|
||||
return this.packageProtectionRulesQueryPayload.pageInfo;
|
||||
protectionRulesQueryPageInfo() {
|
||||
return this.protectionRulesQueryPayload.pageInfo;
|
||||
},
|
||||
packageProtectionRulesQueryResult() {
|
||||
return this.packageProtectionRulesQueryPayload.nodes;
|
||||
protectionRulesQueryResult() {
|
||||
return this.protectionRulesQueryPayload.nodes;
|
||||
},
|
||||
isLoadingPackageProtectionRules() {
|
||||
return this.$apollo.queries.packageProtectionRulesQueryPayload.loading;
|
||||
isLoadingProtectionRules() {
|
||||
return this.$apollo.queries.protectionRulesQueryPayload.loading;
|
||||
},
|
||||
showTopLevelLoadingIcon() {
|
||||
return this.isLoadingPackageProtectionRules && !this.containsTableItems;
|
||||
return this.isLoadingProtectionRules && !this.containsTableItems;
|
||||
},
|
||||
toastMessage() {
|
||||
return this.protectionRuleMutationItem
|
||||
return this.mutationItem
|
||||
? s__('PackageRegistry|Package protection rule updated.')
|
||||
: s__('PackageRegistry|Package protection rule created.');
|
||||
},
|
||||
},
|
||||
apollo: {
|
||||
packageProtectionRulesQueryPayload: {
|
||||
query: packagesProtectionRuleQuery,
|
||||
context: {
|
||||
batchKey: 'PackageRegistryProjectSettings',
|
||||
},
|
||||
variables() {
|
||||
return {
|
||||
projectPath: this.projectPath,
|
||||
...this.packageProtectionRulesQueryPaginationParams,
|
||||
};
|
||||
},
|
||||
update(data) {
|
||||
return data.project?.packagesProtectionRules ?? this.packageProtectionRulesQueryPayload;
|
||||
},
|
||||
error(e) {
|
||||
this.alertErrorMessage = e.message;
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
closeDrawer() {
|
||||
this.showDrawer = false;
|
||||
},
|
||||
refetchProtectionRules() {
|
||||
this.$apollo.queries.packageProtectionRulesQueryPayload.refetch();
|
||||
this.$apollo.queries.protectionRulesQueryPayload.refetch();
|
||||
},
|
||||
onNextPage() {
|
||||
this.packageProtectionRulesQueryPaginationParams = {
|
||||
after: this.packageProtectionRulesQueryPageInfo.endCursor,
|
||||
this.protectionRulesQueryPaginationParams = {
|
||||
after: this.protectionRulesQueryPageInfo.endCursor,
|
||||
first: PAGINATION_DEFAULT_PER_PAGE,
|
||||
};
|
||||
},
|
||||
onPrevPage() {
|
||||
this.packageProtectionRulesQueryPaginationParams = {
|
||||
before: this.packageProtectionRulesQueryPageInfo.startCursor,
|
||||
this.protectionRulesQueryPaginationParams = {
|
||||
before: this.protectionRulesQueryPageInfo.startCursor,
|
||||
last: PAGINATION_DEFAULT_PER_PAGE,
|
||||
};
|
||||
},
|
||||
|
|
@ -167,20 +166,20 @@ export default {
|
|||
this.refetchProtectionRules();
|
||||
},
|
||||
openEditFormDrawer(item) {
|
||||
this.protectionRuleMutationItem = item;
|
||||
this.mutationItem = item;
|
||||
this.showDrawer = true;
|
||||
},
|
||||
openNewFormDrawer() {
|
||||
this.protectionRuleMutationItem = null;
|
||||
this.mutationItem = null;
|
||||
this.showDrawer = true;
|
||||
},
|
||||
showProtectionRuleDeletionConfirmModal(protectionRule) {
|
||||
this.protectionRuleMutationItem = protectionRule;
|
||||
showDeletionConfirmModal(protectionRule) {
|
||||
this.mutationItem = protectionRule;
|
||||
},
|
||||
deleteProtectionRule(protectionRule) {
|
||||
this.clearAlertMessage();
|
||||
|
||||
this.protectionRuleMutationInProgress = true;
|
||||
this.mutationInProgress = true;
|
||||
|
||||
return this.$apollo
|
||||
.mutate({
|
||||
|
|
@ -207,14 +206,14 @@ export default {
|
|||
this.alertErrorMessage = '';
|
||||
},
|
||||
resetProtectionRuleMutation() {
|
||||
this.protectionRuleMutationItem = null;
|
||||
this.protectionRuleMutationInProgress = false;
|
||||
this.mutationItem = null;
|
||||
this.mutationInProgress = false;
|
||||
},
|
||||
isProtectionRuleDeleteButtonDisabled(item) {
|
||||
return this.isProtectionRuleMutationInProgress(item);
|
||||
isDeleteButtonDisabled(item) {
|
||||
return this.isMutationInProgress(item);
|
||||
},
|
||||
isProtectionRuleMutationInProgress(item) {
|
||||
return this.protectionRuleMutationItem === item && this.protectionRuleMutationInProgress;
|
||||
isMutationInProgress(item) {
|
||||
return this.mutationItem === item && this.mutationInProgress;
|
||||
},
|
||||
},
|
||||
fields: [
|
||||
|
|
@ -268,7 +267,7 @@ export default {
|
|||
ref="packagesCrud"
|
||||
:title="$options.i18n.settingBlockTitle"
|
||||
:description="$options.i18n.settingBlockDescription"
|
||||
:toggle-text="$options.i18n.createProtectionRuleText"
|
||||
:toggle-text="s__('PackageRegistry|Add protection rule')"
|
||||
@showForm="openNewFormDrawer"
|
||||
>
|
||||
<template #default>
|
||||
|
|
@ -289,7 +288,7 @@ export default {
|
|||
:fields="fields"
|
||||
stacked="md"
|
||||
:aria-label="$options.i18n.settingBlockTitle"
|
||||
:busy="isLoadingPackageProtectionRules"
|
||||
:busy="isLoadingProtectionRules"
|
||||
>
|
||||
<template #table-busy>
|
||||
<gl-loading-icon size="sm" class="gl-my-5" />
|
||||
|
|
@ -334,8 +333,8 @@ export default {
|
|||
:title="$options.i18n.delete"
|
||||
:aria-label="$options.i18n.delete"
|
||||
data-testid="delete-rule-btn"
|
||||
:disabled="isProtectionRuleDeleteButtonDisabled(item)"
|
||||
@click="showProtectionRuleDeletionConfirmModal(item)"
|
||||
:disabled="isDeleteButtonDisabled(item)"
|
||||
@click="showDeletionConfirmModal(item)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -351,7 +350,7 @@ export default {
|
|||
</template>
|
||||
<template #default>
|
||||
<packages-protection-rule-form
|
||||
:rule="protectionRuleMutationItem"
|
||||
:rule="mutationItem"
|
||||
@cancel="closeDrawer"
|
||||
@submit="handleSubmit"
|
||||
/>
|
||||
|
|
@ -361,7 +360,7 @@ export default {
|
|||
|
||||
<template #pagination>
|
||||
<gl-keyset-pagination
|
||||
v-bind="packageProtectionRulesQueryPageInfo"
|
||||
v-bind="protectionRulesQueryPageInfo"
|
||||
@prev="onPrevPage"
|
||||
@next="onNextPage"
|
||||
/>
|
||||
|
|
@ -369,22 +368,22 @@ export default {
|
|||
</crud-component>
|
||||
|
||||
<gl-modal
|
||||
v-if="protectionRuleMutationItem"
|
||||
v-if="mutationItem"
|
||||
:modal-id="$options.modal.id"
|
||||
size="sm"
|
||||
:title="$options.i18n.protectionRuleDeletionConfirmModal.title"
|
||||
:title="$options.i18n.deletionConfirmModal.title"
|
||||
:action-primary="$options.modalActionPrimary"
|
||||
:action-cancel="$options.modalActionCancel"
|
||||
@primary="deleteProtectionRule(protectionRuleMutationItem)"
|
||||
@primary="deleteProtectionRule(mutationItem)"
|
||||
>
|
||||
<p>
|
||||
<gl-sprintf :message="$options.i18n.protectionRuleDeletionConfirmModal.descriptionWarning">
|
||||
<gl-sprintf :message="$options.i18n.deletionConfirmModal.descriptionWarning">
|
||||
<template #packageNamePattern>
|
||||
<strong>{{ protectionRuleMutationItem.packageNamePattern }}</strong>
|
||||
<strong>{{ mutationItem.packageNamePattern }}</strong>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</p>
|
||||
<p>{{ $options.i18n.protectionRuleDeletionConfirmModal.descriptionConsequence }}</p>
|
||||
<p>{{ $options.i18n.deletionConfirmModal.descriptionConsequence }}</p>
|
||||
</gl-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ query getBlobSearchQuery(
|
|||
$chunkCount: Int
|
||||
$regex: Boolean
|
||||
$includeArchived: Boolean
|
||||
$includeForked: Boolean
|
||||
$excludeForks: Boolean
|
||||
) {
|
||||
blobSearch(
|
||||
search: $search
|
||||
|
|
@ -16,7 +16,7 @@ query getBlobSearchQuery(
|
|||
chunkCount: $chunkCount
|
||||
regex: $regex
|
||||
includeArchived: $includeArchived
|
||||
includeForked: $includeForked
|
||||
excludeForks: $excludeForks
|
||||
) {
|
||||
fileCount
|
||||
files {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ query getBlobSearchCountQuery(
|
|||
$chunkCount: Int
|
||||
$regex: Boolean
|
||||
$includeArchived: Boolean
|
||||
$includeForked: Boolean
|
||||
$excludeForks: Boolean
|
||||
) {
|
||||
blobSearch(
|
||||
search: $search
|
||||
|
|
@ -14,7 +14,7 @@ query getBlobSearchCountQuery(
|
|||
chunkCount: $chunkCount
|
||||
regex: $regex
|
||||
includeArchived: $includeArchived
|
||||
includeForked: $includeForked
|
||||
excludeForks: $excludeForks
|
||||
) {
|
||||
matchCount
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import getBlobSearchQuery from '~/search/graphql/blob_search_zoekt.query.graphql
|
|||
import { ERROR_POLICY_NONE } from '~/lib/graphql';
|
||||
import { parseBoolean } from '~/lib/utils/common_utils';
|
||||
import { logError } from '~/lib/logger';
|
||||
import { EXCLUDE_FORKS_FILTER_PARAM } from '~/search/sidebar/constants';
|
||||
import { DEFAULT_FETCH_CHUNKS } from '../constants';
|
||||
import { RECEIVE_NAVIGATION_COUNT } from '../../store/mutation_types';
|
||||
import EmptyResult from './result_empty.vue';
|
||||
|
|
@ -47,7 +48,7 @@ export default {
|
|||
chunkCount: DEFAULT_FETCH_CHUNKS,
|
||||
regex: parseBoolean(this.query?.regex),
|
||||
includeArchived: parseBoolean(this.query?.include_archived),
|
||||
includeForked: parseBoolean(this.query?.include_forked),
|
||||
excludeForks: parseBoolean(this.query?.[EXCLUDE_FORKS_FILTER_PARAM]),
|
||||
};
|
||||
|
||||
if (this.query?.group_id) {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { InternalEvents } from '~/tracking';
|
|||
import { parseBoolean } from '~/lib/utils/common_utils';
|
||||
import {
|
||||
EVENT_CLICK_ZOEKT_INCLUDE_FORKS_ON_SEARCH_RESULTS_PAGE,
|
||||
INCLUDE_FORKED_FILTER_PARAM,
|
||||
EXCLUDE_FORKS_FILTER_PARAM,
|
||||
} from '~/search/sidebar/constants';
|
||||
|
||||
const trackingMixin = InternalEvents.mixin();
|
||||
|
|
@ -23,21 +23,21 @@ export default {
|
|||
},
|
||||
mixins: [trackingMixin],
|
||||
i18n: {
|
||||
TOOLTIP: s__('GlobalSearch|Include search results from forked projects'),
|
||||
TOOLTIP: s__('GlobalSearch|Exclude search results from forked projects'),
|
||||
HEADER_LABEL: s__('GlobalSearch|Forks'),
|
||||
CHECKBOX_LABEL: s__('GlobalSearch|Include forks'),
|
||||
CHECKBOX_LABEL: s__('GlobalSearch|Exclude forks'),
|
||||
},
|
||||
computed: {
|
||||
...mapState(['urlQuery']),
|
||||
selectedFilter: {
|
||||
get() {
|
||||
return [parseBoolean(this.urlQuery?.[INCLUDE_FORKED_FILTER_PARAM])];
|
||||
return [parseBoolean(this.urlQuery?.[EXCLUDE_FORKS_FILTER_PARAM])];
|
||||
},
|
||||
set(value) {
|
||||
const includeForked = [...value].pop() ?? false;
|
||||
const excludeForks = [...value].pop() ?? false;
|
||||
this.setQuery({
|
||||
key: INCLUDE_FORKED_FILTER_PARAM,
|
||||
value: includeForked?.toString(),
|
||||
key: EXCLUDE_FORKS_FILTER_PARAM,
|
||||
value: excludeForks?.toString(),
|
||||
});
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ export const LANGUAGE_MAX_ITEM_LENGTH = 100;
|
|||
export const INCLUDE_ARCHIVED_FILTER_PARAM = 'include_archived';
|
||||
export const CONFIDENTAL_FILTER_PARAM = 'confidential';
|
||||
export const LABEL_FILTER_PARAM = 'label_name';
|
||||
export const INCLUDE_FORKED_FILTER_PARAM = 'include_forked';
|
||||
export const EXCLUDE_FORKS_FILTER_PARAM = 'exclude_forks';
|
||||
export const LANGUAGE_FILTER_PARAM = 'language';
|
||||
export const SOURCE_BRANCH_PARAM = 'source_branch';
|
||||
export const NOT_SOURCE_BRANCH_PARAM = 'not[source_branch]';
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import {
|
|||
CONFIDENTAL_FILTER_PARAM,
|
||||
INCLUDE_ARCHIVED_FILTER_PARAM,
|
||||
LABEL_FILTER_PARAM,
|
||||
INCLUDE_FORKED_FILTER_PARAM,
|
||||
EXCLUDE_FORKS_FILTER_PARAM,
|
||||
LANGUAGE_FILTER_PARAM,
|
||||
SOURCE_BRANCH_PARAM,
|
||||
NOT_SOURCE_BRANCH_PARAM,
|
||||
|
|
@ -26,7 +26,7 @@ export const SIDEBAR_PARAMS = [
|
|||
LANGUAGE_FILTER_PARAM,
|
||||
LABEL_FILTER_PARAM,
|
||||
INCLUDE_ARCHIVED_FILTER_PARAM,
|
||||
INCLUDE_FORKED_FILTER_PARAM,
|
||||
EXCLUDE_FORKS_FILTER_PARAM,
|
||||
SOURCE_BRANCH_PARAM,
|
||||
NOT_SOURCE_BRANCH_PARAM,
|
||||
AUTHOR_PARAM,
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ export default {
|
|||
support: __('Support'),
|
||||
docs: __('GitLab documentation'),
|
||||
plans: __('Compare GitLab plans'),
|
||||
forum: __('Community forum'),
|
||||
forum: __('GitLab community forum'),
|
||||
contribute: __('Contribute to GitLab'),
|
||||
feedback: __('Provide feedback'),
|
||||
shortcuts: __('Keyboard shortcuts'),
|
||||
|
|
|
|||
|
|
@ -36,6 +36,11 @@ export default {
|
|||
required: false,
|
||||
default: true,
|
||||
},
|
||||
asButton: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
required: false,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
changedIcon() {
|
||||
|
|
@ -79,7 +84,7 @@ export default {
|
|||
|
||||
<template>
|
||||
<gl-button
|
||||
v-if="showIcon"
|
||||
v-if="showIcon && asButton"
|
||||
v-gl-tooltip.right
|
||||
category="tertiary"
|
||||
size="small"
|
||||
|
|
@ -90,6 +95,15 @@ export default {
|
|||
>
|
||||
<gl-icon :name="changedIcon" :size="size" :class="changedIconClass" />
|
||||
</gl-button>
|
||||
<span
|
||||
v-else-if="showIcon"
|
||||
v-gl-tooltip.right="tooltipTitle"
|
||||
:class="{ 'ml-auto': isCentered }"
|
||||
:aria-label="tooltipTitle"
|
||||
class="file-changed-icon"
|
||||
>
|
||||
<gl-icon :name="changedIcon" :size="size" :class="changedIconClass" />
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
|
|
|
|||
|
|
@ -124,49 +124,51 @@ export default {
|
|||
|
||||
<template>
|
||||
<file-header v-if="file.isHeader" :path="file.path" />
|
||||
<div
|
||||
<button
|
||||
v-else
|
||||
:class="fileClass"
|
||||
:title="textForTitle"
|
||||
:data-level="level"
|
||||
class="file-row"
|
||||
role="button"
|
||||
:aria-expanded="file.type === 'tree' ? file.opened.toString() : undefined"
|
||||
@click="clickFile"
|
||||
@mouseleave="$emit('mouseleave', $event)"
|
||||
>
|
||||
<div class="file-row-name-container">
|
||||
<span
|
||||
ref="textOutput"
|
||||
class="file-row-name"
|
||||
:title="file.name"
|
||||
:data-qa-file-name="file.name"
|
||||
data-testid="file-row-name-container"
|
||||
:class="[fileClasses, { 'str-truncated': !truncateMiddle, 'gl-min-w-0': truncateMiddle }]"
|
||||
>
|
||||
<gl-icon
|
||||
v-if="file.linked"
|
||||
v-gl-tooltip="
|
||||
__('This file was linked in the page URL and will appear as the first one in the list')
|
||||
"
|
||||
name="link"
|
||||
:size="16"
|
||||
/>
|
||||
<file-icon
|
||||
class="file-row-icon"
|
||||
:class="{ 'gl-text-subtle': file.type === 'tree' }"
|
||||
:file-name="file.name"
|
||||
:loading="file.loading"
|
||||
:folder="isTree"
|
||||
:opened="file.opened"
|
||||
:size="16"
|
||||
:submodule="file.submodule"
|
||||
/>
|
||||
<gl-truncate v-if="truncateMiddle" :text="file.name" position="middle" class="gl-pr-7" />
|
||||
<template v-else>{{ file.name }}</template>
|
||||
</span>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
ref="textOutput"
|
||||
class="file-row-name"
|
||||
:title="file.name"
|
||||
:data-qa-file-name="file.name"
|
||||
data-testid="file-row-name-container"
|
||||
:class="[fileClasses, { 'str-truncated': !truncateMiddle, 'gl-min-w-0': truncateMiddle }]"
|
||||
>
|
||||
<gl-icon
|
||||
v-if="file.linked"
|
||||
v-gl-tooltip="
|
||||
__('This file was linked in the page URL and will appear as the first one in the list')
|
||||
"
|
||||
name="link"
|
||||
:size="16"
|
||||
/>
|
||||
<file-icon
|
||||
class="gl-mr-2"
|
||||
:class="{ 'gl-text-subtle': file.type === 'tree' }"
|
||||
:file-name="file.name"
|
||||
:loading="file.loading"
|
||||
:folder="isTree"
|
||||
:opened="file.opened"
|
||||
:size="16"
|
||||
:submodule="file.submodule"
|
||||
/>
|
||||
<gl-truncate
|
||||
v-if="truncateMiddle"
|
||||
:text="file.name"
|
||||
position="middle"
|
||||
class="gl-items-center gl-pr-7"
|
||||
/>
|
||||
<template v-else>{{ file.name }}</template>
|
||||
</span>
|
||||
<slot></slot>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
|
|
@ -180,6 +182,7 @@ export default {
|
|||
border-radius: 3px;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
color: unset;
|
||||
}
|
||||
|
||||
.file-row-name-container {
|
||||
|
|
@ -190,18 +193,13 @@ export default {
|
|||
}
|
||||
|
||||
.file-row-name {
|
||||
display: inline-block;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
max-width: inherit;
|
||||
height: 19px;
|
||||
line-height: 16px;
|
||||
line-height: 1rem;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
margin-left: calc(var(--level) * var(--file-row-level-padding, 16px));
|
||||
}
|
||||
|
||||
.file-row-name .file-row-icon {
|
||||
margin-right: 2px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -451,9 +451,6 @@ export default {
|
|||
showWorkItemTree() {
|
||||
return this.findWidget(WIDGET_TYPE_HIERARCHY) && this.allowedChildTypes?.length > 0;
|
||||
},
|
||||
showWorkItemVulnerabilities() {
|
||||
return this.glFeatures.workItemRelatedVulnerabilities;
|
||||
},
|
||||
titleClassHeader() {
|
||||
return {
|
||||
'sm:!gl-hidden gl-mt-3': this.shouldShowAncestors,
|
||||
|
|
@ -1219,7 +1216,6 @@ export default {
|
|||
/>
|
||||
|
||||
<work-item-vulnerabilities
|
||||
v-if="showWorkItemVulnerabilities"
|
||||
:work-item-iid="iid"
|
||||
:work-item-full-path="workItemFullPath"
|
||||
data-testid="work-item-vulnerabilities"
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@
|
|||
padding: $gl-padding-8;
|
||||
|
||||
.issue {
|
||||
background-color: var(--white, $white);
|
||||
background-color: var(--gl-background-color-section);
|
||||
margin-bottom: $gl-padding-8;
|
||||
@apply gl-rounded-base;
|
||||
border: 1px solid var(--gl-border-color-default);
|
||||
border: 1px solid var(--gl-border-color-section);
|
||||
box-shadow: 0 1px 2px $issue-boards-card-shadow;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -300,11 +300,14 @@ $diff-file-header-top: 11px;
|
|||
|
||||
.tree-list-holder {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.file-row {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
.tree-list-holder .file-row {
|
||||
width: calc(100% - #{$gl-spacing-scale-1} * 2);
|
||||
margin: 0 0 0 $gl-spacing-scale-1;
|
||||
border: 0;
|
||||
min-width: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.tree-list-gutter {
|
||||
|
|
|
|||
|
|
@ -116,10 +116,16 @@ module ProjectsHelper
|
|||
end
|
||||
|
||||
def remove_project_message(project)
|
||||
_(
|
||||
"You are going to delete %{project_full_name}. Deleted projects " \
|
||||
"CANNOT be restored! Are you ABSOLUTELY sure?"
|
||||
) % { project_full_name: project.full_name }
|
||||
if project.delayed_deletion_ready?
|
||||
_("Deleting a project places it into a read-only state until %{date}, " \
|
||||
"at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
|
||||
) % { date: permanent_deletion_date_formatted(Date.current) }
|
||||
else
|
||||
_(
|
||||
"You are going to delete %{project_full_name}. Deleted projects " \
|
||||
"CANNOT be restored! Are you ABSOLUTELY sure?"
|
||||
) % { project_full_name: project.full_name }
|
||||
end
|
||||
end
|
||||
|
||||
def link_to_namespace_change_doc
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Packages
|
||||
module Conan
|
||||
module PackageFileable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
has_many :file_metadata, inverse_of: name.demodulize.underscore.to_sym,
|
||||
class_name: 'Packages::Conan::FileMetadatum'
|
||||
has_many :package_files, through: :file_metadata
|
||||
|
||||
def orphan?
|
||||
package_files.empty?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -4,6 +4,7 @@ module Packages
|
|||
module Conan
|
||||
class PackageReference < ApplicationRecord
|
||||
include ShaAttribute
|
||||
include PackageFileable
|
||||
|
||||
REFERENCE_LENGTH_MAX = 40
|
||||
MAX_INFO_SIZE = 20_000
|
||||
|
|
@ -17,7 +18,6 @@ module Packages
|
|||
belongs_to :project
|
||||
|
||||
has_many :package_revisions, inverse_of: :package_reference, class_name: 'Packages::Conan::PackageRevision'
|
||||
has_many :file_metadata, inverse_of: :package_reference, class_name: 'Packages::Conan::FileMetadatum'
|
||||
|
||||
validates :package, :project, presence: true
|
||||
validates :reference, presence: true, format: { with: Gitlab::Regex.conan_package_reference_regex },
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ module Packages
|
|||
module Conan
|
||||
class PackageRevision < ApplicationRecord
|
||||
include ShaAttribute
|
||||
include PackageFileable
|
||||
|
||||
sha_attribute :revision
|
||||
|
||||
|
|
@ -12,8 +13,6 @@ module Packages
|
|||
inverse_of: :package_revisions
|
||||
belongs_to :project
|
||||
|
||||
has_many :file_metadata, inverse_of: :package_revision, class_name: 'Packages::Conan::FileMetadatum'
|
||||
|
||||
validates :package, :package_reference, :project, presence: true
|
||||
validates :revision, presence: true, format: { with: ::Gitlab::Regex.conan_revision_regex_v2 }
|
||||
validates :revision, uniqueness: { scope: [:package_id, :package_reference_id] }, on: %i[create update]
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ module Packages
|
|||
module Conan
|
||||
class RecipeRevision < ApplicationRecord
|
||||
include ShaAttribute
|
||||
include PackageFileable
|
||||
|
||||
sha_attribute :revision
|
||||
|
||||
|
|
@ -12,7 +13,6 @@ module Packages
|
|||
|
||||
has_many :conan_package_references, inverse_of: :recipe_revision,
|
||||
class_name: 'Packages::Conan::PackageReference'
|
||||
has_many :file_metadata, inverse_of: :recipe_revision, class_name: 'Packages::Conan::FileMetadatum'
|
||||
|
||||
validates :package, :project, presence: true
|
||||
validates :revision, presence: true, format: { with: ::Gitlab::Regex.conan_revision_regex_v2 }
|
||||
|
|
|
|||
|
|
@ -475,6 +475,7 @@ class User < ApplicationRecord
|
|||
delegate :pronouns, :pronouns=, to: :user_detail, allow_nil: true
|
||||
delegate :pronunciation, :pronunciation=, to: :user_detail, allow_nil: true
|
||||
delegate :bluesky, :bluesky=, to: :user_detail, allow_nil: true
|
||||
delegate :orcid, :orcid=, to: :user_detail, allow_nil: true
|
||||
delegate :mastodon, :mastodon=, to: :user_detail, allow_nil: true
|
||||
delegate :linkedin, :linkedin=, to: :user_detail, allow_nil: true
|
||||
delegate :twitter, :twitter=, to: :user_detail, allow_nil: true
|
||||
|
|
|
|||
|
|
@ -37,6 +37,15 @@ class UserDetail < ApplicationRecord
|
|||
\z # end of string
|
||||
/x
|
||||
|
||||
ORCID_VALIDATION_REGEX = /
|
||||
\A # beginning of string
|
||||
( #
|
||||
[0-9]{4}- # 4 digits spaced by dash
|
||||
){3} # 3 times
|
||||
[0-9]{4} # end with 4 digits
|
||||
\z # end of string
|
||||
/x
|
||||
|
||||
validates :discord, length: { maximum: DEFAULT_FIELD_LENGTH }, allow_blank: true
|
||||
validate :discord_format
|
||||
validates :linkedin, length: { maximum: DEFAULT_FIELD_LENGTH }, allow_blank: true
|
||||
|
|
@ -47,6 +56,8 @@ class UserDetail < ApplicationRecord
|
|||
message: proc { s_('Profiles|must contain only a bluesky did:plc identifier.') } }
|
||||
validates :mastodon, length: { maximum: DEFAULT_FIELD_LENGTH }, allow_blank: true
|
||||
validate :mastodon_format
|
||||
validates :orcid, length: { maximum: DEFAULT_FIELD_LENGTH }, allow_blank: true
|
||||
validate :orcid_format
|
||||
validates :organization, length: { maximum: DEFAULT_FIELD_LENGTH }, allow_blank: true
|
||||
validates :skype, length: { maximum: DEFAULT_FIELD_LENGTH }, allow_blank: true
|
||||
validates :twitter, length: { maximum: DEFAULT_FIELD_LENGTH }, allow_blank: true
|
||||
|
|
@ -57,7 +68,7 @@ class UserDetail < ApplicationRecord
|
|||
before_save :prevent_nil_fields
|
||||
|
||||
def sanitize_attrs
|
||||
%i[bluesky discord linkedin mastodon skype twitter website_url].each do |attr|
|
||||
%i[bluesky discord linkedin mastodon orcid skype twitter website_url].each do |attr|
|
||||
value = self[attr]
|
||||
self[attr] = Sanitize.clean(value) if value.present?
|
||||
end
|
||||
|
|
@ -77,6 +88,7 @@ class UserDetail < ApplicationRecord
|
|||
self.location = '' if location.nil?
|
||||
self.mastodon = '' if mastodon.nil?
|
||||
self.organization = '' if organization.nil?
|
||||
self.orcid = '' if orcid.nil?
|
||||
self.skype = '' if skype.nil?
|
||||
self.twitter = '' if twitter.nil?
|
||||
self.website_url = '' if website_url.nil?
|
||||
|
|
@ -102,4 +114,10 @@ def mastodon_format
|
|||
errors.add(:mastodon, _('must contain only a mastodon handle.'))
|
||||
end
|
||||
|
||||
def orcid_format
|
||||
return if orcid.blank? || orcid =~ UserDetail::ORCID_VALIDATION_REGEX
|
||||
|
||||
errors.add(:orcid, _('must contain only a orcid ID.'))
|
||||
end
|
||||
|
||||
UserDetail.prepend_mod_with('UserDetail')
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
= link_to _("Explore"), explore_root_path
|
||||
= link_to _("Help"), help_path
|
||||
= link_to _("About GitLab"), ApplicationHelper.promo_url
|
||||
= link_to _("Community forum"), ApplicationHelper.community_forum, target: '_blank', class: 'text-nowrap', rel: 'noopener noreferrer'
|
||||
= link_to _("GitLab community forum"), ApplicationHelper.community_forum, target: '_blank', class: 'text-nowrap', rel: 'noopener noreferrer'
|
||||
- if one_trust_enabled?
|
||||
= render Pajamas::ButtonComponent.new(category: :tertiary, size: :small, button_options: { class: 'ot-sdk-show-settings' }) do
|
||||
= _("Cookie Preferences")
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ module Packages
|
|||
def perform_work
|
||||
return unless artifact
|
||||
|
||||
before_destroy
|
||||
|
||||
begin
|
||||
artifact.transaction do
|
||||
log_metadata(artifact)
|
||||
|
|
@ -48,6 +50,10 @@ module Packages
|
|||
raise NotImplementedError
|
||||
end
|
||||
|
||||
def before_destroy
|
||||
# no op
|
||||
end
|
||||
|
||||
def after_destroy
|
||||
# no op
|
||||
end
|
||||
|
|
|
|||
|
|
@ -32,20 +32,10 @@ module Gitlab
|
|||
|
||||
private
|
||||
|
||||
# Necessary temporarily as new version might process jobs enqueued in old version
|
||||
# TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/520048
|
||||
def ensure_correct_work_item_type(attributes)
|
||||
return attributes unless attributes.key?('correct_work_item_type_id')
|
||||
|
||||
work_item_type_id = attributes['correct_work_item_type_id']
|
||||
|
||||
attributes.except('correct_work_item_type_id').merge('work_item_type_id' => work_item_type_id)
|
||||
end
|
||||
|
||||
def create_issue(issue_attributes, project_id)
|
||||
label_ids = issue_attributes.delete('label_ids')
|
||||
assignee_ids = issue_attributes.delete('assignee_ids')
|
||||
issue_id = insert_and_return_id(ensure_correct_work_item_type(issue_attributes), Issue)
|
||||
issue_id = insert_and_return_id(issue_attributes, Issue)
|
||||
|
||||
label_issue(project_id, issue_id, label_ids)
|
||||
assign_issue(project_id, issue_id, assignee_ids)
|
||||
|
|
|
|||
|
|
@ -13,20 +13,30 @@ module Packages
|
|||
worker_resource_boundary :unknown
|
||||
idempotent!
|
||||
|
||||
delegate :package, :conan_file_metadatum, to: :artifact, private: true
|
||||
delegate :recipe_revision, :package_reference, :package_revision, to: :conan_file_metadatum, private: true
|
||||
|
||||
def max_running_jobs
|
||||
::Gitlab::CurrentSettings.packages_cleanup_package_file_worker_capacity
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def before_destroy
|
||||
# Load the metadatum into the memory for subsequent operations, since the metadatum is deleted
|
||||
# by CASCADE delete when package file is deleted.
|
||||
conan_file_metadatum if package.conan?
|
||||
end
|
||||
|
||||
def after_destroy
|
||||
pkg = artifact.package
|
||||
# Ml::ModelVersion need the package to be able to upload files later
|
||||
# Issue https://gitlab.com/gitlab-org/gitlab/-/issues/461322
|
||||
return if pkg.ml_model?
|
||||
return if package.ml_model?
|
||||
|
||||
pkg.transaction do
|
||||
pkg.destroy if model.for_package_ids(pkg.id).empty?
|
||||
cleanup_conan_objects if package.conan?
|
||||
|
||||
package.transaction do
|
||||
package.destroy if model.for_package_ids(package.id).empty?
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -38,6 +48,16 @@ module Packages
|
|||
model.next_pending_destruction(order_by: :id)
|
||||
end
|
||||
|
||||
def cleanup_conan_objects
|
||||
return unless conan_file_metadatum
|
||||
|
||||
# return early as destroy will trigger the cascading delete
|
||||
return if recipe_revision&.orphan? && recipe_revision.destroy
|
||||
return if package_reference&.orphan? && package_reference.destroy
|
||||
|
||||
package_revision.destroy if package_revision&.orphan?
|
||||
end
|
||||
|
||||
def log_metadata(package_file)
|
||||
log_extra_metadata_on_done(:package_file_id, package_file.id)
|
||||
log_extra_metadata_on_done(:package_id, package_file.package_id)
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
name: improved_review_experience
|
||||
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/525841
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/185795
|
||||
rollout_issue_url:
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/535461
|
||||
milestone: '17.11'
|
||||
group: group::code review
|
||||
type: wip
|
||||
type: beta
|
||||
default_enabled: false
|
||||
|
|
@ -10,3 +10,5 @@ gitlab_schema: gitlab_ci
|
|||
sharding_key:
|
||||
project_id: projects
|
||||
table_size: over_limit
|
||||
removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/191033
|
||||
removed_in_milestone: '18.1'
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# See https://docs.gitlab.com/ee/development/migration_style_guide.html
|
||||
# for more information on how to write migrations for GitLab.
|
||||
|
||||
class AddOrcidToUser < Gitlab::Database::Migration[2.3]
|
||||
USER_DETAILS_FIELD_LIMIT = 256
|
||||
disable_ddl_transaction!
|
||||
|
||||
milestone '18.0'
|
||||
|
||||
def up
|
||||
with_lock_retries do
|
||||
add_column :user_details, :orcid, :text, default: '', null: false, if_not_exists: true
|
||||
end
|
||||
|
||||
add_text_limit :user_details, :orcid, USER_DETAILS_FIELD_LIMIT
|
||||
end
|
||||
|
||||
def down
|
||||
with_lock_retries do
|
||||
remove_column :user_details, :orcid
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class MoveCiBuildsMetadataToDynamicSchema < Gitlab::Database::Migration[2.3]
|
||||
include Gitlab::Database::MigrationHelpers::WraparoundAutovacuum
|
||||
|
||||
milestone '18.1'
|
||||
|
||||
DYNAMIC_SCHEMA = Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA
|
||||
TABLE_NAME = :ci_builds_metadata
|
||||
|
||||
def up
|
||||
return unless can_execute_on?(TABLE_NAME)
|
||||
|
||||
connection.execute(<<~SQL)
|
||||
ALTER TABLE IF EXISTS #{TABLE_NAME} SET SCHEMA #{DYNAMIC_SCHEMA};
|
||||
SQL
|
||||
end
|
||||
|
||||
def down
|
||||
return unless can_execute_on?(TABLE_NAME)
|
||||
|
||||
table_identifier = "#{DYNAMIC_SCHEMA}.#{TABLE_NAME}"
|
||||
|
||||
if table_exists?(table_identifier)
|
||||
connection.execute(<<~SQL)
|
||||
ALTER TABLE IF EXISTS #{table_identifier} SET SCHEMA #{connection.current_schema};
|
||||
SQL
|
||||
else # In tests we set the database from structure.sql, so the table doesn't exist
|
||||
connection.execute(<<~SQL)
|
||||
DROP TABLE IF EXISTS #{DYNAMIC_SCHEMA}.#{TABLE_NAME}_100;
|
||||
CREATE TABLE IF NOT EXISTS #{TABLE_NAME} PARTITION OF p_#{TABLE_NAME} FOR VALUES IN (100);
|
||||
SQL
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
d80822eca404b199f56ef3659fdc09c5c3452dc10e5339762c708ac4e099a5b3
|
||||
|
|
@ -0,0 +1 @@
|
|||
39935f20dc0a333502460214553dc4dd35be6016a17df17e52f0f379cf0a88d3
|
||||
|
|
@ -10901,25 +10901,6 @@ CREATE SEQUENCE ci_builds_metadata_id_seq
|
|||
|
||||
ALTER SEQUENCE ci_builds_metadata_id_seq OWNED BY p_ci_builds_metadata.id;
|
||||
|
||||
CREATE TABLE ci_builds_metadata (
|
||||
project_id bigint NOT NULL,
|
||||
timeout integer,
|
||||
timeout_source integer DEFAULT 1 NOT NULL,
|
||||
interruptible boolean,
|
||||
config_options jsonb,
|
||||
config_variables jsonb,
|
||||
has_exposed_artifacts boolean,
|
||||
environment_auto_stop_in character varying(255),
|
||||
expanded_environment_name character varying(255),
|
||||
secrets jsonb DEFAULT '{}'::jsonb NOT NULL,
|
||||
build_id bigint NOT NULL,
|
||||
id bigint DEFAULT nextval('ci_builds_metadata_id_seq'::regclass) NOT NULL,
|
||||
id_tokens jsonb DEFAULT '{}'::jsonb NOT NULL,
|
||||
partition_id bigint NOT NULL,
|
||||
debug_trace_enabled boolean DEFAULT false NOT NULL,
|
||||
exit_code smallint
|
||||
);
|
||||
|
||||
CREATE TABLE ci_builds_runner_session (
|
||||
id bigint NOT NULL,
|
||||
url character varying NOT NULL,
|
||||
|
|
@ -24075,6 +24056,7 @@ CREATE TABLE user_details (
|
|||
onboarding_status jsonb DEFAULT '{}'::jsonb NOT NULL,
|
||||
bluesky text DEFAULT ''::text NOT NULL,
|
||||
bot_namespace_id bigint,
|
||||
orcid text DEFAULT ''::text NOT NULL,
|
||||
CONSTRAINT check_18a53381cd CHECK ((char_length(bluesky) <= 256)),
|
||||
CONSTRAINT check_245664af82 CHECK ((char_length(webauthn_xid) <= 100)),
|
||||
CONSTRAINT check_444573ee52 CHECK ((char_length(skype) <= 500)),
|
||||
|
|
@ -24084,6 +24066,7 @@ CREATE TABLE user_details (
|
|||
CONSTRAINT check_7d6489f8f3 CHECK ((char_length(linkedin) <= 500)),
|
||||
CONSTRAINT check_7fe2044093 CHECK ((char_length(website_url) <= 500)),
|
||||
CONSTRAINT check_8a7fcf8a60 CHECK ((char_length(location) <= 500)),
|
||||
CONSTRAINT check_99b0365865 CHECK ((char_length(orcid) <= 256)),
|
||||
CONSTRAINT check_a73b398c60 CHECK ((char_length(phone) <= 50)),
|
||||
CONSTRAINT check_eeeaf8d4f0 CHECK ((char_length(pronouns) <= 50)),
|
||||
CONSTRAINT check_f1a8a05b9a CHECK ((char_length(mastodon) <= 500)),
|
||||
|
|
@ -26600,8 +26583,6 @@ ALTER TABLE ONLY uploads_9ba88c4165 ATTACH PARTITION bulk_import_export_upload_u
|
|||
|
||||
ALTER TABLE ONLY p_ci_builds ATTACH PARTITION ci_builds FOR VALUES IN ('100');
|
||||
|
||||
ALTER TABLE ONLY p_ci_builds_metadata ATTACH PARTITION ci_builds_metadata FOR VALUES IN ('100');
|
||||
|
||||
ALTER TABLE ONLY p_ci_job_artifacts ATTACH PARTITION ci_job_artifacts FOR VALUES IN ('100', '101');
|
||||
|
||||
ALTER TABLE ONLY p_ci_pipelines ATTACH PARTITION ci_pipelines FOR VALUES IN ('100', '101', '102');
|
||||
|
|
@ -29115,12 +29096,6 @@ ALTER TABLE ONLY ci_build_report_results
|
|||
ALTER TABLE ONLY ci_build_trace_chunks
|
||||
ADD CONSTRAINT ci_build_trace_chunks_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY p_ci_builds_metadata
|
||||
ADD CONSTRAINT p_ci_builds_metadata_pkey PRIMARY KEY (id, partition_id);
|
||||
|
||||
ALTER TABLE ONLY ci_builds_metadata
|
||||
ADD CONSTRAINT ci_builds_metadata_pkey PRIMARY KEY (id, partition_id);
|
||||
|
||||
ALTER TABLE ONLY p_ci_builds
|
||||
ADD CONSTRAINT p_ci_builds_pkey PRIMARY KEY (id, partition_id);
|
||||
|
||||
|
|
@ -30279,6 +30254,9 @@ ALTER TABLE ONLY p_ci_build_trace_metadata
|
|||
ALTER TABLE ONLY p_ci_builds_execution_configs
|
||||
ADD CONSTRAINT p_ci_builds_execution_configs_pkey PRIMARY KEY (id, partition_id);
|
||||
|
||||
ALTER TABLE ONLY p_ci_builds_metadata
|
||||
ADD CONSTRAINT p_ci_builds_metadata_pkey PRIMARY KEY (id, partition_id);
|
||||
|
||||
ALTER TABLE ONLY p_ci_finished_build_ch_sync_events
|
||||
ADD CONSTRAINT p_ci_finished_build_ch_sync_events_pkey PRIMARY KEY (build_id, partition);
|
||||
|
||||
|
|
@ -34124,22 +34102,6 @@ CREATE INDEX index_ci_build_trace_chunks_on_partition_id_build_id ON ci_build_tr
|
|||
|
||||
CREATE INDEX index_ci_build_trace_chunks_on_project_id ON ci_build_trace_chunks USING btree (project_id);
|
||||
|
||||
CREATE INDEX p_ci_builds_metadata_build_id_idx ON ONLY p_ci_builds_metadata USING btree (build_id) WHERE (has_exposed_artifacts IS TRUE);
|
||||
|
||||
CREATE INDEX index_ci_builds_metadata_on_build_id_and_has_exposed_artifacts ON ci_builds_metadata USING btree (build_id) WHERE (has_exposed_artifacts IS TRUE);
|
||||
|
||||
CREATE INDEX p_ci_builds_metadata_build_id_id_idx ON ONLY p_ci_builds_metadata USING btree (build_id) INCLUDE (id) WHERE (interruptible = true);
|
||||
|
||||
CREATE INDEX index_ci_builds_metadata_on_build_id_and_id_and_interruptible ON ci_builds_metadata USING btree (build_id) INCLUDE (id) WHERE (interruptible = true);
|
||||
|
||||
CREATE UNIQUE INDEX p_ci_builds_metadata_build_id_partition_id_idx ON ONLY p_ci_builds_metadata USING btree (build_id, partition_id);
|
||||
|
||||
CREATE UNIQUE INDEX index_ci_builds_metadata_on_build_id_partition_id_unique ON ci_builds_metadata USING btree (build_id, partition_id);
|
||||
|
||||
CREATE INDEX p_ci_builds_metadata_project_id_idx ON ONLY p_ci_builds_metadata USING btree (project_id);
|
||||
|
||||
CREATE INDEX index_ci_builds_metadata_on_project_id ON ci_builds_metadata USING btree (project_id);
|
||||
|
||||
CREATE INDEX p_ci_builds_auto_canceled_by_id_idx ON ONLY p_ci_builds USING btree (auto_canceled_by_id) WHERE (auto_canceled_by_id IS NOT NULL);
|
||||
|
||||
CREATE INDEX index_ci_builds_on_auto_canceled_by_id ON ci_builds USING btree (auto_canceled_by_id) WHERE (auto_canceled_by_id IS NOT NULL);
|
||||
|
|
@ -38302,6 +38264,14 @@ CREATE INDEX organization_detail_uploads_uploaded_by_user_id_idx ON organization
|
|||
|
||||
CREATE INDEX organization_detail_uploads_uploader_path_idx ON organization_detail_uploads USING btree (uploader, path);
|
||||
|
||||
CREATE INDEX p_ci_builds_metadata_build_id_id_idx ON ONLY p_ci_builds_metadata USING btree (build_id) INCLUDE (id) WHERE (interruptible = true);
|
||||
|
||||
CREATE INDEX p_ci_builds_metadata_build_id_idx ON ONLY p_ci_builds_metadata USING btree (build_id) WHERE (has_exposed_artifacts IS TRUE);
|
||||
|
||||
CREATE UNIQUE INDEX p_ci_builds_metadata_build_id_partition_id_idx ON ONLY p_ci_builds_metadata USING btree (build_id, partition_id);
|
||||
|
||||
CREATE INDEX p_ci_builds_metadata_project_id_idx ON ONLY p_ci_builds_metadata USING btree (project_id);
|
||||
|
||||
CREATE INDEX p_ci_builds_scheduled_at_idx ON ONLY p_ci_builds USING btree (scheduled_at) WHERE ((scheduled_at IS NOT NULL) AND ((type)::text = 'Ci::Build'::text) AND ((status)::text = 'scheduled'::text));
|
||||
|
||||
CREATE UNIQUE INDEX p_ci_builds_token_encrypted_partition_id_idx ON ONLY p_ci_builds USING btree (token_encrypted, partition_id) WHERE (token_encrypted IS NOT NULL);
|
||||
|
|
@ -40502,8 +40472,6 @@ ALTER INDEX index_uploads_9ba88c4165_on_uploader_and_path ATTACH PARTITION bulk_
|
|||
|
||||
ALTER INDEX p_ci_builds_status_created_at_project_id_idx ATTACH PARTITION ci_builds_gitlab_monitor_metrics;
|
||||
|
||||
ALTER INDEX p_ci_builds_metadata_pkey ATTACH PARTITION ci_builds_metadata_pkey;
|
||||
|
||||
ALTER INDEX p_ci_builds_pkey ATTACH PARTITION ci_builds_pkey;
|
||||
|
||||
ALTER INDEX p_ci_job_artifacts_pkey ATTACH PARTITION ci_job_artifacts_pkey;
|
||||
|
|
@ -40670,14 +40638,6 @@ ALTER INDEX tmp_p_ci_builds_trigger_request_id_idx ATTACH PARTITION index_437b18
|
|||
|
||||
ALTER INDEX index_ci_runner_machines_on_executor_type ATTACH PARTITION index_aa3b4fe8c6;
|
||||
|
||||
ALTER INDEX p_ci_builds_metadata_build_id_idx ATTACH PARTITION index_ci_builds_metadata_on_build_id_and_has_exposed_artifacts;
|
||||
|
||||
ALTER INDEX p_ci_builds_metadata_build_id_id_idx ATTACH PARTITION index_ci_builds_metadata_on_build_id_and_id_and_interruptible;
|
||||
|
||||
ALTER INDEX p_ci_builds_metadata_build_id_partition_id_idx ATTACH PARTITION index_ci_builds_metadata_on_build_id_partition_id_unique;
|
||||
|
||||
ALTER INDEX p_ci_builds_metadata_project_id_idx ATTACH PARTITION index_ci_builds_metadata_on_project_id;
|
||||
|
||||
ALTER INDEX p_ci_builds_auto_canceled_by_id_idx ATTACH PARTITION index_ci_builds_on_auto_canceled_by_id;
|
||||
|
||||
ALTER INDEX p_ci_builds_commit_id_stage_idx_created_at_idx ATTACH PARTITION index_ci_builds_on_commit_id_and_stage_idx_and_created_at;
|
||||
|
|
|
|||
|
|
@ -2,13 +2,14 @@
|
|||
stage: Tenant Scale
|
||||
group: Geo
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
gitlab_dedicated: yes
|
||||
title: Secondary runners
|
||||
---
|
||||
|
||||
{{< details >}}
|
||||
|
||||
- Tier: Premium, Ultimate
|
||||
- Offering: GitLab Self-Managed
|
||||
- Offering: GitLab Self-Managed, GitLab Dedicated
|
||||
|
||||
{{< /details >}}
|
||||
|
||||
|
|
@ -29,6 +30,12 @@ The jobs that start during the first stage of a pipeline almost always have thei
|
|||
|
||||
## Use secondary runners with a Location Aware public URL (Unified URL)
|
||||
|
||||
{{< details >}}
|
||||
|
||||
- Offering: GitLab Self-Managed
|
||||
|
||||
{{< /details >}}
|
||||
|
||||
Using [Location-Aware DNS](_index.md#configure-location-aware-dns), with the feature flag enabled works with no extra configuration. After you install and register a runner in the same location as a secondary site, it automatically talks to the closest site, and only proxies to the primary if the secondary is out of date.
|
||||
|
||||
## Use secondary runners with separate URLs
|
||||
|
|
@ -44,6 +51,12 @@ When executing [a planned failover](../disaster_recovery/planned_failover.md), s
|
|||
|
||||
### With Location Aware public URL
|
||||
|
||||
{{< details >}}
|
||||
|
||||
- Offering: GitLab Self-Managed
|
||||
|
||||
{{< /details >}}
|
||||
|
||||
When using [Location-Aware DNS](_index.md#configure-location-aware-dns), all runners automatically connect to the closest Geo site.
|
||||
|
||||
When failing over to a new primary:
|
||||
|
|
|
|||
|
|
@ -2,14 +2,15 @@
|
|||
stage: Create
|
||||
group: Source Code
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
description: Configure a Diagrams.net integration for GitLab Self-Managed.
|
||||
description: Configure a Diagrams.net integration for GitLab.
|
||||
gitlab_dedicated: yes
|
||||
title: Diagrams.net
|
||||
---
|
||||
|
||||
{{< details >}}
|
||||
|
||||
- Tier: Free, Premium, Ultimate
|
||||
- Offering: GitLab Self-Managed
|
||||
- Offering: GitLab Self-Managed, GitLab Dedicated
|
||||
|
||||
{{< /details >}}
|
||||
|
||||
|
|
@ -25,7 +26,7 @@ The diagram editor is available in both the plain text editor and the rich text
|
|||
|
||||
On GitLab.com, this integration is enabled for all SaaS users and does not require any additional configuration.
|
||||
|
||||
On GitLab Self-Managed, you can choose to integrate with the free [diagrams.net](https://www.drawio.com/)
|
||||
On GitLab Self-Managed and GitLab Dedicated, you can choose to integrate with the free [diagrams.net](https://www.drawio.com/)
|
||||
website, or host your own diagrams.net site in offline environments.
|
||||
|
||||
To set up the integration, you must:
|
||||
|
|
|
|||
|
|
@ -2,13 +2,14 @@
|
|||
stage: Plan
|
||||
group: Project Management
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
gitlab_dedicated: yes
|
||||
title: Kroki
|
||||
---
|
||||
|
||||
{{< details >}}
|
||||
|
||||
- Tier: Free, Premium, Ultimate
|
||||
- Offering: GitLab Self-Managed
|
||||
- Offering: GitLab Self-Managed, GitLab Dedicated
|
||||
|
||||
{{< /details >}}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,13 +2,14 @@
|
|||
stage: Systems
|
||||
group: Distribution
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
gitlab_dedicated: yes
|
||||
title: Polling interval multiplier
|
||||
---
|
||||
|
||||
{{< details >}}
|
||||
|
||||
- Tier: Free, Premium, Ultimate
|
||||
- Offering: GitLab Self-Managed
|
||||
- Offering: GitLab Self-Managed, GitLab Dedicated
|
||||
|
||||
{{< /details >}}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,13 +2,14 @@
|
|||
stage: Software Supply Chain Security
|
||||
group: Authorization
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
gitlab_dedicated: yes
|
||||
title: Review spam logs
|
||||
---
|
||||
|
||||
{{< details >}}
|
||||
|
||||
- Tier: Free, Premium, Ultimate
|
||||
- Offering: GitLab Self-Managed
|
||||
- Offering: GitLab Self-Managed, GitLab Dedicated
|
||||
|
||||
{{< /details >}}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,14 +2,15 @@
|
|||
stage: Create
|
||||
group: Source Code
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
description: Define limits for deprecated APIs on GitLab Self-Managed.
|
||||
description: Define limits for deprecated APIs on GitLab.
|
||||
gitlab_dedicated: yes
|
||||
title: Deprecated API rate limits
|
||||
---
|
||||
|
||||
{{< details >}}
|
||||
|
||||
- Tier: Free, Premium, Ultimate
|
||||
- Offering: GitLab Self-Managed
|
||||
- Offering: GitLab Self-Managed, GitLab Dedicated
|
||||
|
||||
{{< /details >}}
|
||||
|
||||
|
|
|
|||
|
|
@ -28236,6 +28236,7 @@ four standard [pagination arguments](#pagination-arguments):
|
|||
| ---- | ---- | ----------- |
|
||||
| <a id="groupdependenciescomponentids"></a>`componentIds` | [`[SbomComponentID!]`](#sbomcomponentid) | Filter dependencies by component IDs. |
|
||||
| <a id="groupdependenciescomponentnames"></a>`componentNames` | [`[String!]`](#string) | Filter dependencies by component names. |
|
||||
| <a id="groupdependenciescomponentversions"></a>`componentVersions` | [`[String!]`](#string) | Filter dependencies by component versions. |
|
||||
| <a id="groupdependenciespackagemanagers"></a>`packageManagers` | [`[PackageManager!]`](#packagemanager) | Filter dependencies by package managers. |
|
||||
| <a id="groupdependenciessort"></a>`sort` | [`DependencySort`](#dependencysort) | Sort dependencies by given criteria. |
|
||||
| <a id="groupdependenciessourcetypes"></a>`sourceTypes` | [`[SbomSourceType!]`](#sbomsourcetype) | Filter dependencies by source type. |
|
||||
|
|
@ -28261,6 +28262,7 @@ four standard [pagination arguments](#pagination-arguments):
|
|||
| ---- | ---- | ----------- |
|
||||
| <a id="groupdependencyaggregationscomponentids"></a>`componentIds` | [`[SbomComponentID!]`](#sbomcomponentid) | Filter dependencies by component IDs. |
|
||||
| <a id="groupdependencyaggregationscomponentnames"></a>`componentNames` | [`[String!]`](#string) | Filter dependencies by component names. |
|
||||
| <a id="groupdependencyaggregationscomponentversions"></a>`componentVersions` | [`[String!]`](#string) | Filter dependencies by component versions. |
|
||||
| <a id="groupdependencyaggregationspackagemanagers"></a>`packageManagers` | [`[PackageManager!]`](#packagemanager) | Filter dependencies by package managers. |
|
||||
| <a id="groupdependencyaggregationsprojectcountmax"></a>`projectCountMax` | [`Int`](#int) | Filter dependencies by maximum project count. |
|
||||
| <a id="groupdependencyaggregationsprojectcountmin"></a>`projectCountMin` | [`Int`](#int) | Filter dependencies by minimum project count. |
|
||||
|
|
@ -35874,6 +35876,7 @@ four standard [pagination arguments](#pagination-arguments):
|
|||
| ---- | ---- | ----------- |
|
||||
| <a id="projectdependenciescomponentids"></a>`componentIds` | [`[SbomComponentID!]`](#sbomcomponentid) | Filter dependencies by component IDs. |
|
||||
| <a id="projectdependenciescomponentnames"></a>`componentNames` | [`[String!]`](#string) | Filter dependencies by component names. |
|
||||
| <a id="projectdependenciescomponentversions"></a>`componentVersions` | [`[String!]`](#string) | Filter dependencies by component versions. |
|
||||
| <a id="projectdependenciespackagemanagers"></a>`packageManagers` | [`[PackageManager!]`](#packagemanager) | Filter dependencies by package managers. |
|
||||
| <a id="projectdependenciessort"></a>`sort` | [`DependencySort`](#dependencysort) | Sort dependencies by given criteria. |
|
||||
| <a id="projectdependenciessourcetypes"></a>`sourceTypes` | [`[SbomSourceType!]`](#sbomsourcetype) | Filter dependencies by source type. |
|
||||
|
|
|
|||
|
|
@ -2,13 +2,14 @@
|
|||
stage: Fulfillment
|
||||
group: Utilization
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
gitlab_dedicated: yes
|
||||
title: License API
|
||||
---
|
||||
|
||||
{{< details >}}
|
||||
|
||||
- Tier: Free, Premium, Ultimate
|
||||
- Offering: GitLab Self-Managed
|
||||
- Offering: GitLab Self-Managed, GitLab Dedicated
|
||||
|
||||
{{< /details >}}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,13 +2,14 @@
|
|||
stage: Systems
|
||||
group: Distribution
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
gitlab_dedicated: yes
|
||||
title: Sidekiq Metrics API
|
||||
---
|
||||
|
||||
{{< details >}}
|
||||
|
||||
- Tier: Free, Premium, Ultimate
|
||||
- Offering: GitLab Self-Managed
|
||||
- Offering: GitLab Self-Managed, GitLab Dedicated
|
||||
|
||||
{{< /details >}}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ You can incorporate [Docker](https://www.docker.com) into your CI/CD workflow in
|
|||
or in the GitLab container registry. Your job then runs in a container that's based on the image.
|
||||
The container has all the Node dependencies you need to build your app.
|
||||
|
||||
- **Use [Docker](using_docker_build.md) or [kaniko](using_kaniko.md) to build Docker images.**
|
||||
- **Use [Docker](using_docker_build.md) to build Docker images.**
|
||||
|
||||
You can create CI/CD jobs to build Docker images and publish
|
||||
them to a container registry.
|
||||
|
|
|
|||
|
|
@ -748,11 +748,8 @@ and [using the OverlayFS storage driver](https://docs.docker.com/storage/storage
|
|||
|
||||
## Docker alternatives
|
||||
|
||||
To build Docker images without enabling privileged mode on the runner, you can
|
||||
use one of these alternatives:
|
||||
|
||||
- [`kaniko`](using_kaniko.md).
|
||||
- [`buildah`](#buildah-example).
|
||||
To build Docker images without enabling privileged mode on the runner,
|
||||
use [`buildah`](#buildah-example).
|
||||
|
||||
### Buildah example
|
||||
|
||||
|
|
@ -987,7 +984,7 @@ To resolve this issue:
|
|||
image:
|
||||
name: docker:19.03
|
||||
variables:
|
||||
DOCKER_HOST: tcp://localhost:2375
|
||||
DOCKER_HOST: tcp://localhost:2375
|
||||
DOCKER_TLS_CERTDIR: ""
|
||||
CA_CERTIFICATE: "$CA_CERTIFICATE"
|
||||
services:
|
||||
|
|
@ -999,7 +996,7 @@ To resolve this issue:
|
|||
echo "$CA_CERTIFICATE" > /usr/local/share/ca-certificates/custom-ca.crt && \
|
||||
update-ca-certificates && \
|
||||
dockerd-entrypoint.sh || exit
|
||||
script:
|
||||
script:
|
||||
- docker info
|
||||
- docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD $DOCKER_REGISTRY
|
||||
- docker build -t "${DOCKER_REGISTRY}/my-app:${CI_COMMIT_REF_NAME}" .
|
||||
|
|
|
|||
|
|
@ -3,17 +3,18 @@ stage: Fulfillment
|
|||
group: Subscription Management
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
description: Seat usage, compute minutes, storage limits, renewal info.
|
||||
gitlab_dedicated: yes
|
||||
title: Troubleshooting GitLab subscription
|
||||
---
|
||||
|
||||
{{< details >}}
|
||||
|
||||
- Tier: Premium, Ultimate
|
||||
- Offering: GitLab.com, GitLab Self-Managed
|
||||
- Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
|
||||
|
||||
{{< /details >}}
|
||||
|
||||
When you purchase or use subscriptions for GitLab.com or GitLab Self-Managed, you might encounter the following issues.
|
||||
When you purchase or use subscriptions for GitLab, you might encounter the following issues.
|
||||
|
||||
## Credit card declined
|
||||
|
||||
|
|
@ -93,7 +94,7 @@ Ensure that you have the Owner role for that namespace, and review the [transfer
|
|||
|
||||
## Subscription data fails to synchronize
|
||||
|
||||
On GitLab Self-Managed, your subscription data might fail to synchronize.
|
||||
On GitLab Self-Managed or GitLab Dedicated, your subscription data might fail to synchronize.
|
||||
This issue can occur when network traffic between your GitLab instance and certain
|
||||
IP addresses is not allowed.
|
||||
|
||||
|
|
|
|||
|
|
@ -356,16 +356,10 @@ For each selected vulnerability:
|
|||
|
||||
- [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/13216) in GitLab 17.9 [with a flag](../../../administration/feature_flags.md) named `enhanced_vulnerability_bulk_actions`. Disabled by default.
|
||||
- [Enabled on GitLab.com, GitLab Self-Managed, and GitLab Dedicated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/190213) in GitLab 18.0.
|
||||
- [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/515204) in GitLab 18.1. Feature flag `enhanced_vulnerability_bulk_actions` removed.
|
||||
|
||||
{{< /history >}}
|
||||
|
||||
{{< alert type="flag" >}}
|
||||
|
||||
The availability of this feature is controlled by a feature flag.
|
||||
For more information, see the history.
|
||||
|
||||
{{< /alert >}}
|
||||
|
||||
You can link one or more vulnerabilities to existing issues in the vulnerability report.
|
||||
|
||||
Prerequisites:
|
||||
|
|
|
|||
|
|
@ -4,4 +4,4 @@ source "https://rubygems.org"
|
|||
|
||||
gemspec
|
||||
|
||||
gem 'activerecord', '~> 7.0.8' # rubocop:disable Gemfile/MissingFeatureCategory
|
||||
gem 'activerecord', '~> 7.1.5.1' # rubocop:disable Gemfile/MissingFeatureCategory
|
||||
|
|
|
|||
|
|
@ -7,19 +7,33 @@ PATH
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
activemodel (7.0.8.7)
|
||||
activesupport (= 7.0.8.7)
|
||||
activerecord (7.0.8.7)
|
||||
activemodel (= 7.0.8.7)
|
||||
activesupport (= 7.0.8.7)
|
||||
activesupport (7.0.8.7)
|
||||
activemodel (7.1.5.1)
|
||||
activesupport (= 7.1.5.1)
|
||||
activerecord (7.1.5.1)
|
||||
activemodel (= 7.1.5.1)
|
||||
activesupport (= 7.1.5.1)
|
||||
timeout (>= 0.4.0)
|
||||
activesupport (7.1.5.1)
|
||||
base64
|
||||
benchmark (>= 0.3)
|
||||
bigdecimal
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
connection_pool (>= 2.2.5)
|
||||
drb
|
||||
i18n (>= 1.6, < 2)
|
||||
logger (>= 1.4.2)
|
||||
minitest (>= 5.1)
|
||||
mutex_m
|
||||
securerandom (>= 0.3)
|
||||
tzinfo (~> 2.0)
|
||||
ast (2.4.2)
|
||||
base64 (0.2.0)
|
||||
benchmark (0.4.0)
|
||||
bigdecimal (3.1.9)
|
||||
concurrent-ruby (1.2.2)
|
||||
connection_pool (2.5.3)
|
||||
diff-lcs (1.5.0)
|
||||
drb (2.2.1)
|
||||
gitlab-styles (10.1.0)
|
||||
rubocop (~> 1.50.2)
|
||||
rubocop-graphql (~> 0.18)
|
||||
|
|
@ -29,8 +43,10 @@ GEM
|
|||
i18n (1.13.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
json (2.6.3)
|
||||
logger (1.7.0)
|
||||
mini_portile2 (2.8.2)
|
||||
minitest (5.18.0)
|
||||
mutex_m (0.3.0)
|
||||
parallel (1.23.0)
|
||||
parser (3.2.2.3)
|
||||
ast (~> 2.4.1)
|
||||
|
|
@ -83,8 +99,10 @@ GEM
|
|||
rubocop-capybara (~> 2.17)
|
||||
rubocop-factory_bot (~> 2.22)
|
||||
ruby-progressbar (1.13.0)
|
||||
securerandom (0.4.1)
|
||||
sqlite3 (1.6.3)
|
||||
mini_portile2 (~> 2.8.0)
|
||||
timeout (0.4.3)
|
||||
tzinfo (2.0.6)
|
||||
concurrent-ruby (~> 1.0)
|
||||
unicode-display_width (2.4.2)
|
||||
|
|
@ -93,7 +111,7 @@ PLATFORMS
|
|||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
activerecord (~> 7.0.8)
|
||||
activerecord (~> 7.1.5.1)
|
||||
activerecord-gitlab!
|
||||
gitlab-styles (~> 10.1.0)
|
||||
rspec (~> 3.12)
|
||||
|
|
@ -102,18 +120,25 @@ DEPENDENCIES
|
|||
sqlite3 (~> 1.6)
|
||||
|
||||
CHECKSUMS
|
||||
activemodel (7.0.8.7) sha256=f13b04bb055c1e85b965ce40b0a2e671b8d97835083597bc7fbc04cde0f40a83
|
||||
activerecord (7.0.8.7) sha256=f94fc8510e58a18e462c5ee8862c9be75e2bfad0688e8d022b86a6e05df2a45a
|
||||
activemodel (7.1.5.1) sha256=74727466854a7fbdfe8f2702ca3112b23877500d4926bf7e02e921ad542191f1
|
||||
activerecord (7.1.5.1) sha256=f40ad1609bf33b9ba5bdc4e16d80a77b1517153234ceb413d31d635d7b91f1e3
|
||||
activerecord-gitlab (0.2.0)
|
||||
activesupport (7.0.8.7) sha256=df4702375de924aae81709c831605317c5417f0bd9e502a0373ff84a067204ff
|
||||
activesupport (7.1.5.1) sha256=9f0c482e473b9868cb3dfe3e9db549a3bd2302c02e4f595a5caac144a8c7cfb8
|
||||
ast (2.4.2) sha256=1e280232e6a33754cde542bc5ef85520b74db2aac73ec14acef453784447cc12
|
||||
base64 (0.2.0) sha256=0f25e9b21a02a0cc0cea8ef92b2041035d39350946e8789c562b2d1a3da01507
|
||||
benchmark (0.4.0) sha256=0f12f8c495545e3710c3e4f0480f63f06b4c842cc94cec7f33a956f5180e874a
|
||||
bigdecimal (3.1.9) sha256=2ffc742031521ad69c2dfc815a98e426a230a3d22aeac1995826a75dabfad8cc
|
||||
concurrent-ruby (1.2.2) sha256=3879119b8b75e3b62616acc256c64a134d0b0a7a9a3fcba5a233025bcde22c4f
|
||||
connection_pool (2.5.3) sha256=cfd74a82b9b094d1ce30c4f1a346da23ee19dc8a062a16a85f58eab1ced4305b
|
||||
diff-lcs (1.5.0) sha256=49b934001c8c6aedb37ba19daec5c634da27b318a7a3c654ae979d6ba1929b67
|
||||
drb (2.2.1) sha256=e9d472bf785f558b96b25358bae115646da0dbfd45107ad858b0bc0d935cb340
|
||||
gitlab-styles (10.1.0) sha256=f42745f5397d042fe24cf2d0eb56c995b37f9f43d8fb79b834d197a1cafdc84a
|
||||
i18n (1.13.0) sha256=1d24cacd941be578faa7fc5d537d573a3e76e2822ce7dffc0c71c41ba91e63fa
|
||||
json (2.6.3) sha256=86aaea16adf346a2b22743d88f8dcceeb1038843989ab93cda44b5176c845459
|
||||
logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203
|
||||
mini_portile2 (2.8.2) sha256=46b2d244cc6ff01a89bf61274690c09fdbdca47a84ae9eac39039e81231aee7c
|
||||
minitest (5.18.0) sha256=06f43aa0692ce3acf19cb5bc539ad2c6095ca3d2c7e5fbafc58a7d847e898745
|
||||
mutex_m (0.3.0) sha256=cfcb04ac16b69c4813777022fdceda24e9f798e48092a2b817eb4c0a782b0751
|
||||
parallel (1.23.0) sha256=27154713ad6ef32fa3dcb7788a721d6c07bca77e72443b4c6080a14145288c49
|
||||
parser (3.2.2.3) sha256=10685f358ab36ffea2252dc4952e5b8fad3a297a8152a85f59adc982747b91eb
|
||||
racc (1.7.1) sha256=af64124836fdd3c00e830703d7f873ea5deabde923f37006a39f5a5e0da16387
|
||||
|
|
@ -135,7 +160,9 @@ CHECKSUMS
|
|||
rubocop-rails (2.20.2) sha256=d20cbd613900fa22bcf85a7fba78ab68b21fc4f90b1e73c97284d40674332417
|
||||
rubocop-rspec (2.22.0) sha256=2d7493222c81c78ad304ddd81aaf64b3543bcfac6d3d8706c220331921753a03
|
||||
ruby-progressbar (1.13.0) sha256=80fc9c47a9b640d6834e0dc7b3c94c9df37f08cb072b7761e4a71e22cff29b33
|
||||
securerandom (0.4.1) sha256=cc5193d414a4341b6e225f0cb4446aceca8e50d5e1888743fac16987638ea0b1
|
||||
sqlite3 (1.6.3) sha256=67b476378889b15c93f9b78d39f6d92636dda414194d570d3a1b27514a9e2541
|
||||
timeout (0.4.3) sha256=9509f079b2b55fe4236d79633bd75e34c1c1e7e3fb4b56cb5fda61f80a0fe30e
|
||||
tzinfo (2.0.6) sha256=8daf828cc77bcf7d63b0e3bdb6caa47e2272dcfaf4fbfe46f8c3a9df087a829b
|
||||
unicode-display_width (2.4.2) sha256=6a10205d1a19ca790c4e53064ba93f09d9eb234bf6bd135d9deb6001c21428be
|
||||
|
||||
|
|
|
|||
|
|
@ -4,4 +4,4 @@ source "https://rubygems.org"
|
|||
|
||||
gemspec
|
||||
|
||||
gem 'activerecord', '~> 7.1' # rubocop:disable Gemfile/MissingFeatureCategory
|
||||
gem 'activerecord', '~> 7.2' # rubocop:disable Gemfile/MissingFeatureCategory
|
||||
|
|
|
|||
|
|
@ -7,24 +7,27 @@ PATH
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
activemodel (7.1.3.4)
|
||||
activesupport (= 7.1.3.4)
|
||||
activerecord (7.1.3.4)
|
||||
activemodel (= 7.1.3.4)
|
||||
activesupport (= 7.1.3.4)
|
||||
activemodel (7.2.2.1)
|
||||
activesupport (= 7.2.2.1)
|
||||
activerecord (7.2.2.1)
|
||||
activemodel (= 7.2.2.1)
|
||||
activesupport (= 7.2.2.1)
|
||||
timeout (>= 0.4.0)
|
||||
activesupport (7.1.3.4)
|
||||
activesupport (7.2.2.1)
|
||||
base64
|
||||
benchmark (>= 0.3)
|
||||
bigdecimal
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
concurrent-ruby (~> 1.0, >= 1.3.1)
|
||||
connection_pool (>= 2.2.5)
|
||||
drb
|
||||
i18n (>= 1.6, < 2)
|
||||
logger (>= 1.4.2)
|
||||
minitest (>= 5.1)
|
||||
mutex_m
|
||||
tzinfo (~> 2.0)
|
||||
securerandom (>= 0.3)
|
||||
tzinfo (~> 2.0, >= 2.0.5)
|
||||
ast (2.4.2)
|
||||
base64 (0.2.0)
|
||||
benchmark (0.4.0)
|
||||
bigdecimal (3.1.8)
|
||||
concurrent-ruby (1.3.3)
|
||||
connection_pool (2.4.1)
|
||||
|
|
@ -39,8 +42,8 @@ GEM
|
|||
i18n (1.14.5)
|
||||
concurrent-ruby (~> 1.0)
|
||||
json (2.7.2)
|
||||
logger (1.7.0)
|
||||
minitest (5.24.1)
|
||||
mutex_m (0.2.0)
|
||||
parallel (1.25.1)
|
||||
parser (3.3.4.0)
|
||||
ast (~> 2.4.1)
|
||||
|
|
@ -98,6 +101,7 @@ GEM
|
|||
rubocop-rspec_rails (2.29.0)
|
||||
rubocop (~> 1.40)
|
||||
ruby-progressbar (1.13.0)
|
||||
securerandom (0.4.1)
|
||||
sqlite3 (1.7.3-aarch64-linux)
|
||||
sqlite3 (1.7.3-arm-linux)
|
||||
sqlite3 (1.7.3-arm64-darwin)
|
||||
|
|
@ -105,7 +109,7 @@ GEM
|
|||
sqlite3 (1.7.3-x86_64-darwin)
|
||||
sqlite3 (1.7.3-x86_64-linux)
|
||||
strscan (3.1.0)
|
||||
timeout (0.4.1)
|
||||
timeout (0.4.3)
|
||||
tzinfo (2.0.6)
|
||||
concurrent-ruby (~> 1.0)
|
||||
unicode-display_width (2.5.0)
|
||||
|
|
@ -119,7 +123,7 @@ PLATFORMS
|
|||
x86_64-linux
|
||||
|
||||
DEPENDENCIES
|
||||
activerecord (~> 7.1)
|
||||
activerecord (~> 7.2)
|
||||
activerecord-gitlab!
|
||||
gitlab-styles (~> 10.1.0)
|
||||
rspec (~> 3.12)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
if ::ActiveRecord::VERSION::STRING >= "7.2"
|
||||
if ::ActiveRecord::VERSION::STRING >= "7.3"
|
||||
raise 'New version of active-record detected, please remove or update this patch'
|
||||
end
|
||||
|
||||
|
|
@ -9,7 +9,7 @@ module ActiveRecord
|
|||
module GitlabPatches
|
||||
module Partitioning
|
||||
module Base
|
||||
if ::ActiveRecord::VERSION::STRING <= "7.1"
|
||||
if ::ActiveRecord::VERSION::STRING <= "7.2"
|
||||
def _query_constraints_hash
|
||||
if self.class.query_constraints_list.nil?
|
||||
{ @primary_key => id_in_database }
|
||||
|
|
@ -28,7 +28,7 @@ module ActiveRecord
|
|||
@query_constraints_list = columns_list.map(&:to_s)
|
||||
end
|
||||
|
||||
if ::ActiveRecord::VERSION::STRING <= "7.1"
|
||||
if ::ActiveRecord::VERSION::STRING <= "7.2"
|
||||
def query_constraints_list # :nodoc:
|
||||
@query_constraints_list ||= if base_class? || primary_key != base_class.primary_key
|
||||
primary_key if primary_key.is_a?(Array)
|
||||
|
|
|
|||
|
|
@ -69,7 +69,11 @@ module API
|
|||
|
||||
filter_params = declared_params(include_missing: false).merge(only_personal: true)
|
||||
|
||||
present paginate(find_snippets(user: nil, params: filter_params)), with: Entities::PersonalSnippet, current_user: current_user
|
||||
present(
|
||||
paginate(find_snippets(user: nil, params: filter_params)),
|
||||
with: Entities::PersonalSnippet,
|
||||
current_user: current_user
|
||||
)
|
||||
end
|
||||
|
||||
desc 'List all snippets current_user has access to' do
|
||||
|
|
@ -141,7 +145,11 @@ module API
|
|||
authorize! :create_snippet
|
||||
|
||||
attrs = process_create_params(declared_params(include_missing: false))
|
||||
service_response = ::Snippets::CreateService.new(project: nil, current_user: current_user, params: attrs).execute
|
||||
service_response = ::Snippets::CreateService.new(
|
||||
project: nil,
|
||||
current_user: current_user,
|
||||
params: attrs
|
||||
).execute
|
||||
snippet = service_response.payload[:snippet]
|
||||
|
||||
if service_response.success?
|
||||
|
|
@ -188,7 +196,12 @@ module API
|
|||
validate_params_for_multiple_files(snippet)
|
||||
|
||||
attrs = process_update_params(declared_params(include_missing: false))
|
||||
service_response = ::Snippets::UpdateService.new(project: nil, current_user: current_user, params: attrs, perform_spam_check: true).execute(snippet)
|
||||
service_response = ::Snippets::UpdateService.new(
|
||||
project: nil,
|
||||
current_user: current_user,
|
||||
params: attrs,
|
||||
perform_spam_check: true
|
||||
).execute(snippet)
|
||||
|
||||
snippet = service_response.payload[:snippet]
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ module Gitlab
|
|||
module Memory
|
||||
class Watchdog
|
||||
class Configurator
|
||||
DEFAULT_PUMA_WORKER_RSS_LIMIT_MB = 1200
|
||||
DEFAULT_PUMA_WORKER_RSS_LIMIT_MB = 1500
|
||||
DEFAULT_SLEEP_INTERVAL_S = 60
|
||||
DEFAULT_SIDEKIQ_SLEEP_INTERVAL_S = 3
|
||||
MIN_SIDEKIQ_SLEEP_INTERVAL_S = 2
|
||||
|
|
|
|||
|
|
@ -15136,9 +15136,6 @@ msgstr ""
|
|||
msgid "Commit|containing commit"
|
||||
msgstr ""
|
||||
|
||||
msgid "Community forum"
|
||||
msgstr ""
|
||||
|
||||
msgid "Company"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -26501,6 +26498,9 @@ msgstr ""
|
|||
msgid "File added."
|
||||
msgstr ""
|
||||
|
||||
msgid "File browser"
|
||||
msgstr ""
|
||||
|
||||
msgid "File changed and moved."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -26558,6 +26558,9 @@ msgstr ""
|
|||
msgid "File too large. Secure files must be less than %{limit} MB."
|
||||
msgstr ""
|
||||
|
||||
msgid "File tree"
|
||||
msgstr ""
|
||||
|
||||
msgid "File upload error."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -28166,6 +28169,9 @@ msgstr ""
|
|||
msgid "GitLab commit"
|
||||
msgstr ""
|
||||
|
||||
msgid "GitLab community forum"
|
||||
msgstr ""
|
||||
|
||||
msgid "GitLab container registry API not supported"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -28706,6 +28712,12 @@ msgstr ""
|
|||
msgid "GlobalSearch|Epics"
|
||||
msgstr ""
|
||||
|
||||
msgid "GlobalSearch|Exclude forks"
|
||||
msgstr ""
|
||||
|
||||
msgid "GlobalSearch|Exclude search results from forked projects"
|
||||
msgstr ""
|
||||
|
||||
msgid "GlobalSearch|Explore"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -28757,15 +28769,9 @@ msgstr ""
|
|||
msgid "GlobalSearch|Include archived"
|
||||
msgstr ""
|
||||
|
||||
msgid "GlobalSearch|Include forks"
|
||||
msgstr ""
|
||||
|
||||
msgid "GlobalSearch|Include search results from archived projects"
|
||||
msgstr ""
|
||||
|
||||
msgid "GlobalSearch|Include search results from forked projects"
|
||||
msgstr ""
|
||||
|
||||
msgid "GlobalSearch|Incremental indexing queue length"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -73184,6 +73190,9 @@ msgstr ""
|
|||
msgid "must contain only a mastodon handle."
|
||||
msgstr ""
|
||||
|
||||
msgid "must contain only a orcid ID."
|
||||
msgstr ""
|
||||
|
||||
msgid "must have a repository"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,14 @@ module QA
|
|||
element 'submit-review-button'
|
||||
end
|
||||
|
||||
view 'app/assets/javascripts/batch_comments/components/review_drawer.vue' do
|
||||
element 'submit-review-button'
|
||||
end
|
||||
|
||||
view 'app/assets/javascripts/batch_comments/components/submit_review_button.vue' do
|
||||
element 'review-drawer-toggle'
|
||||
end
|
||||
|
||||
view 'app/assets/javascripts/diffs/components/compare_dropdown_layout.vue' do
|
||||
element 'version-dropdown-content'
|
||||
end
|
||||
|
|
@ -185,11 +193,7 @@ module QA
|
|||
end
|
||||
end
|
||||
|
||||
within_element('review-bar-content') do
|
||||
click_element('review-preview-dropdown')
|
||||
end
|
||||
|
||||
click_element('submit-review-dropdown')
|
||||
all_elements('review-drawer-toggle', minimum: 1).first.click
|
||||
click_element('submit-review-button')
|
||||
|
||||
# After clicking the button, wait for the review bar to disappear
|
||||
|
|
|
|||
|
|
@ -3,17 +3,14 @@
|
|||
module QA
|
||||
RSpec.describe 'Create' do
|
||||
# admin required to check if feature flag is enabled
|
||||
describe 'Batch comments in merge request', :smoke, :requires_admin, product_group: :code_review do
|
||||
describe 'Batch comments in merge request', :smoke, product_group: :code_review do
|
||||
let(:project) { create(:project, name: 'project-with-merge-request') }
|
||||
let(:merge_request) do
|
||||
create(:merge_request, title: 'This is a merge request', description: 'Great feature', project: project)
|
||||
end
|
||||
|
||||
it 'user submits a non-diff review',
|
||||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347777',
|
||||
feature_flag: { name: :improved_review_experience } do
|
||||
skip('improved_review_experience FF is WIP') if Runtime::Feature.enabled?('improved_review_experience')
|
||||
|
||||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347777' do
|
||||
Flow::Login.sign_in
|
||||
|
||||
merge_request.visit!
|
||||
|
|
@ -30,10 +27,7 @@ module QA
|
|||
end
|
||||
|
||||
it 'user submits a diff review',
|
||||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347778',
|
||||
feature_flag: { name: :improved_review_experience } do
|
||||
skip('improved_review_experience FF is WIP') if Runtime::Feature.enabled?('improved_review_experience')
|
||||
|
||||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347778' do
|
||||
Flow::Login.sign_in
|
||||
|
||||
merge_request.visit!
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Admin::IntegrationsController, feature_category: :integrations do
|
||||
RSpec.describe Admin::IntegrationsController, :with_current_organization, feature_category: :integrations do
|
||||
let_it_be(:admin) { create(:admin) }
|
||||
let_it_be(:organization) { create(:organization, :default) }
|
||||
let_it_be(:organization) { current_organization }
|
||||
|
||||
before do
|
||||
stub_feature_flags(remove_monitor_metrics: false)
|
||||
|
|
@ -45,14 +45,12 @@ RSpec.describe Admin::IntegrationsController, feature_category: :integrations do
|
|||
describe '#update' do
|
||||
include JiraIntegrationHelpers
|
||||
|
||||
let_it_be(:organization) { create(:organization) }
|
||||
let(:integration) { create(:jira_integration, :instance) }
|
||||
let(:integration_name) { integration.class.to_param }
|
||||
|
||||
before do
|
||||
stub_jira_integration_test
|
||||
allow(PropagateIntegrationWorker).to receive(:perform_async)
|
||||
allow(Current).to receive(:organization).and_return(organization)
|
||||
|
||||
put :update, params: { id: integration_name, service: params }
|
||||
end
|
||||
|
|
|
|||
|
|
@ -65,7 +65,6 @@ RSpec.describe 'Database schema',
|
|||
chat_teams: %w[team_id],
|
||||
ci_builds: %w[project_id runner_id user_id erased_by_id trigger_request_id partition_id
|
||||
auto_canceled_by_partition_id execution_config_id upstream_pipeline_partition_id],
|
||||
ci_builds_metadata: %w[partition_id project_id build_id],
|
||||
ci_build_needs: %w[project_id],
|
||||
ci_build_pending_states: %w[project_id],
|
||||
ci_build_trace_chunks: %w[project_id],
|
||||
|
|
|
|||
|
|
@ -13,8 +13,6 @@ RSpec.describe 'Merge request > Batch comments', :js, feature_category: :code_re
|
|||
end
|
||||
|
||||
before do
|
||||
stub_feature_flags(improved_review_experience: false)
|
||||
|
||||
project.add_maintainer(user)
|
||||
|
||||
sign_in(user)
|
||||
|
|
@ -27,21 +25,22 @@ RSpec.describe 'Merge request > Batch comments', :js, feature_category: :code_re
|
|||
|
||||
expect(find('.draft-note')).to have_content('Line is wrong')
|
||||
|
||||
expect(page).to have_selector('[data-testid="review_bar_component"]')
|
||||
|
||||
expect(find('[data-testid="review_bar_component"] .gl-badge')).to have_content('1')
|
||||
expect(first('[data-testid="review-drawer-toggle"] .gl-badge')).to have_content('1')
|
||||
end
|
||||
|
||||
it 'publishes review' do
|
||||
write_diff_comment
|
||||
|
||||
page.within('.review-bar-content') do
|
||||
click_button 'Finish review'
|
||||
click_button 'Submit review'
|
||||
page.within '.merge-request-tabs-holder' do
|
||||
click_button 'Your review'
|
||||
end
|
||||
|
||||
click_button 'Submit review'
|
||||
|
||||
wait_for_requests
|
||||
|
||||
find_by_scrolling("[id='#{sample_compare.changes[0][:line_code]}']")
|
||||
|
||||
expect(page).not_to have_selector('.draft-note', text: 'Line is wrong')
|
||||
|
||||
expect(page).to have_selector('.note:not(.draft-note)', text: 'Line is wrong')
|
||||
|
|
@ -150,7 +149,9 @@ RSpec.describe 'Merge request > Batch comments', :js, feature_category: :code_re
|
|||
|
||||
expect(page).to have_selector('.draft-note', text: 'Its a draft comment')
|
||||
|
||||
click_button('Pending comments')
|
||||
page.within '.merge-request-tabs-holder' do
|
||||
click_button 'Your review'
|
||||
end
|
||||
|
||||
expect(page).to have_text('2 pending comments')
|
||||
end
|
||||
|
|
@ -160,7 +161,9 @@ RSpec.describe 'Merge request > Batch comments', :js, feature_category: :code_re
|
|||
|
||||
expect(page).to have_selector('.note:not(.draft-note)', text: 'Its a regular comment')
|
||||
|
||||
click_button('Pending comments')
|
||||
page.within '.merge-request-tabs-holder' do
|
||||
click_button 'Your review'
|
||||
end
|
||||
|
||||
expect(page).to have_text('1 pending comment')
|
||||
end
|
||||
|
|
@ -180,7 +183,7 @@ RSpec.describe 'Merge request > Batch comments', :js, feature_category: :code_re
|
|||
expect(find('.new .draft-note')).to have_content('Line is wrong')
|
||||
expect(find('.old .draft-note')).to have_content('Another wrong line')
|
||||
|
||||
expect(find('.review-bar-content .gl-badge')).to have_content('2')
|
||||
expect(first('[data-testid="review-drawer-toggle"] .gl-badge')).to have_content('2')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -206,11 +209,12 @@ RSpec.describe 'Merge request > Batch comments', :js, feature_category: :code_re
|
|||
|
||||
write_reply_to_discussion(resolve: true)
|
||||
|
||||
page.within('.review-bar-content') do
|
||||
click_button 'Finish review'
|
||||
click_button 'Submit review'
|
||||
page.within '.merge-request-tabs-holder' do
|
||||
click_button 'Your review'
|
||||
end
|
||||
|
||||
click_button 'Submit review'
|
||||
|
||||
wait_for_requests
|
||||
|
||||
page.within(first('.discussions-counter')) do
|
||||
|
|
@ -249,11 +253,12 @@ RSpec.describe 'Merge request > Batch comments', :js, feature_category: :code_re
|
|||
|
||||
write_reply_to_discussion(button_text: 'Start a review', unresolve: true)
|
||||
|
||||
page.within('.review-bar-content') do
|
||||
click_button 'Finish review'
|
||||
click_button 'Submit review'
|
||||
page.within '.merge-request-tabs-holder' do
|
||||
click_button 'Your review'
|
||||
end
|
||||
|
||||
click_button 'Submit review'
|
||||
|
||||
wait_for_requests
|
||||
|
||||
page.within(first('.discussions-counter')) do
|
||||
|
|
|
|||
|
|
@ -12,20 +12,19 @@ RSpec.describe 'Merge request > User sees merge request file tree sidebar', :js,
|
|||
let(:sidebar_scroller) { sidebar.find('.vue-recycle-scroller') }
|
||||
|
||||
before do
|
||||
stub_feature_flags(improved_review_experience: false)
|
||||
sign_in(user)
|
||||
visit diffs_project_merge_request_path(project, merge_request)
|
||||
wait_for_requests
|
||||
end
|
||||
|
||||
it 'sees file tree sidebar' do
|
||||
expect(page).to have_selector('.file-row[role=button]')
|
||||
expect(page).to have_selector('[data-testid="file-tree-container"]')
|
||||
end
|
||||
|
||||
shared_examples 'last entry clickable' do
|
||||
specify do
|
||||
sidebar_scroller.execute_script('this.scrollBy(0,99999)')
|
||||
button = find_all('.file-row[role=button]').last
|
||||
button = find_all('[data-testid="file-tree-container"] nav button').last
|
||||
title = button.find('[data-testid=file-row-name-container]')[:title]
|
||||
expect(button.obscured?).to be_falsy
|
||||
button.click
|
||||
|
|
@ -35,26 +34,6 @@ RSpec.describe 'Merge request > User sees merge request file tree sidebar', :js,
|
|||
|
||||
it_behaves_like 'last entry clickable'
|
||||
|
||||
context 'when has started a review' do
|
||||
before do
|
||||
add_diff_line_draft_comment('foo', find('.line_holder', match: :first))
|
||||
# wait for review bar to appear
|
||||
find_by_testid('review_bar_component')
|
||||
# wait for sidebar to adjust
|
||||
sleep(1)
|
||||
end
|
||||
|
||||
it_behaves_like 'last entry clickable'
|
||||
|
||||
context 'when scrolled into full view' do
|
||||
before do
|
||||
sidebar.execute_script("this.scrollIntoView({ block: 'end' })")
|
||||
end
|
||||
|
||||
it_behaves_like 'last entry clickable'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when viewing using file-by-file mode' do
|
||||
let(:user) { create(:user, view_diffs_file_by_file: true) }
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ describe('Diff File Row component', () => {
|
|||
file: {},
|
||||
size: 16,
|
||||
showTooltip: true,
|
||||
asButton: false,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -170,14 +170,14 @@ describe('Diffs tree list component', () => {
|
|||
return treeEntries;
|
||||
};
|
||||
|
||||
describe('default', () => {
|
||||
beforeEach(() => {
|
||||
createComponent();
|
||||
});
|
||||
it('renders empty text', () => {
|
||||
createComponent();
|
||||
expect(wrapper.text()).toContain('No files found');
|
||||
});
|
||||
|
||||
it('renders empty text', () => {
|
||||
expect(wrapper.text()).toContain('No files found');
|
||||
});
|
||||
it('renders title', () => {
|
||||
createComponent();
|
||||
expect(wrapper.find('h2').text()).toContain('Files');
|
||||
});
|
||||
|
||||
it('renders file count', () => {
|
||||
|
|
|
|||
|
|
@ -64,7 +64,6 @@ describe('your work groups resolver', () => {
|
|||
fullName: 'frontend-fixtures-group',
|
||||
parent: { id: null },
|
||||
webUrl: mockGroup.web_url,
|
||||
organizationEditPath: '',
|
||||
descriptionHtml: '',
|
||||
avatarUrl: null,
|
||||
descendantGroupsCount: 1,
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ describe('ForksFilter', () => {
|
|||
it('wraps the label element with a tooltip', () => {
|
||||
const tooltip = getBinding(findCheckboxFilterLabel().element, 'gl-tooltip');
|
||||
expect(tooltip).toBeDefined();
|
||||
expect(tooltip.value).toBe('Include search results from forked projects');
|
||||
expect(tooltip.value).toBe('Exclude search results from forked projects');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -71,19 +71,19 @@ describe('ForksFilter', () => {
|
|||
it('wraps the label element with a tooltip', () => {
|
||||
const tooltip = getBinding(findCheckboxFilterLabel().element, 'gl-tooltip');
|
||||
expect(tooltip).toBeDefined();
|
||||
expect(tooltip.value).toBe('Include search results from forked projects');
|
||||
expect(tooltip.value).toBe('Exclude search results from forked projects');
|
||||
});
|
||||
});
|
||||
|
||||
describe.each`
|
||||
include_forked | checkboxState
|
||||
${'true'} | ${'true'}
|
||||
${'sdfsdf'} | ${'false'}
|
||||
${''} | ${'false'}
|
||||
${'false'} | ${'false'}
|
||||
`('selectedFilter', ({ include_forked, checkboxState }) => {
|
||||
exclude_forks | checkboxState
|
||||
${'true'} | ${'true'}
|
||||
${'sdfsdf'} | ${'false'}
|
||||
${''} | ${'false'}
|
||||
${'false'} | ${'false'}
|
||||
`('selectedFilter', ({ exclude_forks, checkboxState }) => {
|
||||
beforeEach(() => {
|
||||
createComponent({ urlQuery: { include_forked } });
|
||||
createComponent({ urlQuery: { exclude_forks } });
|
||||
});
|
||||
|
||||
it('renders the component', () => {
|
||||
|
|
@ -101,7 +101,7 @@ describe('ForksFilter', () => {
|
|||
findCheckboxFilter().vm.$emit('input', selectedFilter);
|
||||
|
||||
expect(defaultActions.setQuery).toHaveBeenCalledWith(expect.any(Object), {
|
||||
key: 'include_forked',
|
||||
key: 'exclude_forks',
|
||||
value: 'false',
|
||||
});
|
||||
expect(selectedFilter).toEqual([false]);
|
||||
|
|
|
|||
|
|
@ -108,4 +108,12 @@ describe('Changed file icon', () => {
|
|||
|
||||
expect(findIconName()).toEqual(iconName);
|
||||
});
|
||||
|
||||
it('can be rendered as span', () => {
|
||||
factory({
|
||||
asButton: false,
|
||||
});
|
||||
|
||||
expect(wrapper.element.tagName).toBe('SPAN');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -34,6 +34,14 @@ describe('File row component', () => {
|
|||
expect(name.text().trim()).toEqual(fileName);
|
||||
});
|
||||
|
||||
it('renders as button', () => {
|
||||
createComponent({
|
||||
file: file('t4'),
|
||||
level: 0,
|
||||
});
|
||||
expect(wrapper.find('button').exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('renders the full path as title', () => {
|
||||
const filePath = 'path/to/file/with a very long folder name/';
|
||||
const fileName = 'foo.txt';
|
||||
|
|
|
|||
|
|
@ -965,6 +965,34 @@ RSpec.describe ProjectsHelper, feature_category: :source_code_management do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#remove_project_message' do
|
||||
subject(:message) { helper.remove_project_message(project) }
|
||||
|
||||
before do
|
||||
allow(project).to receive(:delayed_deletion_ready?).and_return(enabled)
|
||||
end
|
||||
|
||||
context 'when project has delayed deletion enabled' do
|
||||
let(:enabled) { true }
|
||||
|
||||
specify do
|
||||
deletion_date = helper.permanent_deletion_date_formatted(Date.current)
|
||||
|
||||
expect(message).to eq "Deleting a project places it into a read-only state until #{deletion_date}, " \
|
||||
"at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
|
||||
end
|
||||
end
|
||||
|
||||
context 'when project has delayed deletion disabled' do
|
||||
let(:enabled) { false }
|
||||
|
||||
specify do
|
||||
expect(message).to eq "You are going to delete #{project.full_name}. Deleted projects CANNOT be " \
|
||||
"restored! Are you ABSOLUTELY sure?"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#project_permissions_panel_data' do
|
||||
subject { helper.project_permissions_panel_data(project) }
|
||||
|
||||
|
|
|
|||
|
|
@ -12,9 +12,14 @@ RSpec.describe Gitlab::Database::PartitionHelpers, feature_category: :database d
|
|||
describe "#partition?" do
|
||||
subject(:is_partitioned) { model.partition?(table_name) }
|
||||
|
||||
let(:table_name) { 'ci_builds_metadata' }
|
||||
|
||||
context "when a partition table exist" do
|
||||
let(:table_name) { '_test_ci_builds_metadata' }
|
||||
|
||||
before do
|
||||
model.connection.create_table("#{table_name}_p", options: 'PARTITION BY LIST (id)')
|
||||
model.connection.execute("CREATE TABLE #{table_name} PARTITION OF #{table_name}_p FOR VALUES IN (1)")
|
||||
end
|
||||
|
||||
context 'when the view postgres_partitions exists' do
|
||||
it 'calls the view', :aggregate_failures do
|
||||
expect(Gitlab::Database::PostgresPartition).to receive(:partition_exists?).with(table_name).and_call_original
|
||||
|
|
|
|||
|
|
@ -151,7 +151,14 @@ RSpec.describe Gitlab::Database::PostgresPartition, type: :model, feature_catego
|
|||
subject { described_class.partition_exists?(table_name) }
|
||||
|
||||
context 'when the partition exists' do
|
||||
let(:table_name) { "ci_builds_metadata" }
|
||||
let(:table_name) { "_test_partition_02" }
|
||||
|
||||
before do
|
||||
ActiveRecord::Base.connection.execute(<<~SQL)
|
||||
CREATE TABLE #{table_name} PARTITION OF public._test_partitioned_table
|
||||
FOR VALUES FROM ('2020-02-01') to ('2020-03-01');
|
||||
SQL
|
||||
end
|
||||
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
|
|
@ -167,7 +174,14 @@ RSpec.describe Gitlab::Database::PostgresPartition, type: :model, feature_catego
|
|||
subject { described_class.legacy_partition_exists?(table_name) }
|
||||
|
||||
context 'when the partition exists' do
|
||||
let(:table_name) { "ci_builds_metadata" }
|
||||
let(:table_name) { "_test_partition_02" }
|
||||
|
||||
before do
|
||||
ActiveRecord::Base.connection.execute(<<~SQL)
|
||||
CREATE TABLE #{table_name} PARTITION OF public._test_partitioned_table
|
||||
FOR VALUES FROM ('2020-02-01') to ('2020-03-01');
|
||||
SQL
|
||||
end
|
||||
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
|
|
|
|||
|
|
@ -80,7 +80,6 @@ RSpec.describe 'new tables missing sharding_key', feature_category: :cell do
|
|||
# 2. It does not yet have a foreign key as the index is still being backfilled
|
||||
let(:allowed_to_be_missing_foreign_key) do
|
||||
[
|
||||
'ci_builds_metadata.project_id',
|
||||
'ci_deleted_objects.project_id', # LFK already present on p_ci_builds and cascade delete all ci resources
|
||||
'ci_job_artifacts.project_id',
|
||||
'ci_namespace_monthly_usages.namespace_id', # https://gitlab.com/gitlab-org/gitlab/-/issues/321400
|
||||
|
|
|
|||
|
|
@ -20,12 +20,7 @@ RSpec.describe Gitlab::ImportExport::Json::StreamingSerializer, :clean_gitlab_re
|
|||
approvals_before_merge: 1)
|
||||
end
|
||||
|
||||
let_it_be(:issue) do
|
||||
# TODO: .reload can be removed after the migration https://gitlab.com/gitlab-org/gitlab/-/issues/497857
|
||||
create(:issue,
|
||||
assignees: [user],
|
||||
project: exportable).reload
|
||||
end
|
||||
let_it_be(:issue) { create(:issue, assignees: [user], project: exportable) }
|
||||
|
||||
let(:exportable_path) { 'project' }
|
||||
let(:logger) { Gitlab::Export::Logger.build }
|
||||
|
|
@ -367,8 +362,7 @@ RSpec.describe Gitlab::ImportExport::Json::StreamingSerializer, :clean_gitlab_re
|
|||
|
||||
describe 'with inaccessible associations' do
|
||||
let_it_be(:milestone) { create(:milestone, project: exportable) }
|
||||
# TODO: .reload can be removed after the migration https://gitlab.com/gitlab-org/gitlab/-/issues/497857
|
||||
let_it_be(:issue) { create(:issue, assignees: [user], project: exportable, milestone: milestone).reload }
|
||||
let_it_be(:issue) { create(:issue, assignees: [user], project: exportable, milestone: milestone) }
|
||||
let_it_be(:label1) { create(:label, project: exportable) }
|
||||
let_it_be(:label2) { create(:label, project: exportable) }
|
||||
let_it_be(:link1) { create(:label_link, label: label1, target: issue) }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
require_migration!
|
||||
|
||||
RSpec.describe MoveCiBuildsMetadataToDynamicSchema, :migration, feature_category: :continuous_integration do
|
||||
let(:migration) { described_class.new }
|
||||
let(:table_name) { described_class::TABLE_NAME }
|
||||
let(:identifier) { "#{described_class::DYNAMIC_SCHEMA}.#{table_name}" }
|
||||
|
||||
describe '#up' do
|
||||
it 'moves the table into the dynamic schema' do
|
||||
expect(table_exists?(table_name)).to be_truthy
|
||||
|
||||
migration.up
|
||||
|
||||
expect(table_exists?(table_name)).to be_falsey
|
||||
expect(table_exists?(identifier)).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
describe '#down' do
|
||||
context 'when the partition exists in the dynamic schema' do
|
||||
before do
|
||||
migration.up
|
||||
|
||||
ApplicationRecord.connection.execute(<<~SQL)
|
||||
DROP TABLE IF EXISTS #{identifier}_100;
|
||||
CREATE TABLE IF NOT EXISTS #{identifier} PARTITION OF p_#{table_name} FOR VALUES IN (100);
|
||||
SQL
|
||||
end
|
||||
|
||||
it 'moves the table into the current schema' do
|
||||
expect(table_exists?(identifier)).to be_truthy
|
||||
|
||||
migration.down
|
||||
|
||||
expect(table_exists?(table_name)).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the partition does not exist in the dynamic schema' do
|
||||
before do
|
||||
migration.up
|
||||
|
||||
ApplicationRecord.connection.execute(<<~SQL)
|
||||
DROP TABLE IF EXISTS #{identifier};
|
||||
CREATE TABLE IF NOT EXISTS #{identifier}_100 PARTITION OF p_#{table_name} FOR VALUES IN (100);
|
||||
SQL
|
||||
end
|
||||
|
||||
it 'creates the table into the current schema' do
|
||||
expect(table_exists?(identifier)).to be_falsey
|
||||
expect(table_exists?("#{identifier}_100")).to be_truthy
|
||||
|
||||
migration.down
|
||||
|
||||
expect(table_exists?(table_name)).to be_truthy
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def table_exists?(name)
|
||||
ApplicationRecord.connection.table_exists?(name)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Packages::Conan::PackageFileable, type: :model, feature_category: :package_registry do
|
||||
let_it_be(:instance) { build(:conan_recipe_revision) }
|
||||
|
||||
describe 'associations' do
|
||||
subject { instance }
|
||||
|
||||
it 'has many file_metadata' do
|
||||
is_expected.to have_many(:file_metadata)
|
||||
end
|
||||
|
||||
it 'has many package_files through file_metadata' do
|
||||
is_expected.to have_many(:package_files).through(:file_metadata)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#orphan?' do
|
||||
subject { instance.orphan? }
|
||||
|
||||
context 'when package_files is empty' do
|
||||
it 'returns true' do
|
||||
is_expected.to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
context 'when package_files is not empty' do
|
||||
let_it_be(:package_file) do
|
||||
create(:conan_package_file, :conan_recipe_file, package: instance.package, conan_recipe_revision: instance)
|
||||
end
|
||||
|
||||
it 'returns false' do
|
||||
is_expected.to be_falsey
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -3,6 +3,8 @@
|
|||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Packages::Conan::PackageReference, type: :model, feature_category: :package_registry do
|
||||
it { is_expected.to be_a(Packages::Conan::PackageFileable) }
|
||||
|
||||
describe 'associations' do
|
||||
it 'belongs to package' do
|
||||
is_expected.to belong_to(:package).class_name('Packages::Conan::Package').inverse_of(:conan_package_references)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ require 'spec_helper'
|
|||
RSpec.describe Packages::Conan::PackageRevision, type: :model, feature_category: :package_registry do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
it { is_expected.to be_a(Packages::Conan::PackageFileable) }
|
||||
|
||||
describe 'associations' do
|
||||
it 'belongs to package' do
|
||||
is_expected.to belong_to(:package).class_name('Packages::Conan::Package').inverse_of(:conan_package_revisions)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ require 'spec_helper'
|
|||
RSpec.describe Packages::Conan::RecipeRevision, type: :model, feature_category: :package_registry do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
it { is_expected.to be_a(Packages::Conan::PackageFileable) }
|
||||
|
||||
describe 'associations' do
|
||||
it 'belongs to package' do
|
||||
is_expected.to belong_to(:package).class_name('Packages::Conan::Package').inverse_of(:conan_recipe_revisions)
|
||||
|
|
|
|||
|
|
@ -385,6 +385,44 @@ RSpec.describe UserDetail, feature_category: :system_access do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#orcid' do
|
||||
context 'when orcid is set' do
|
||||
let_it_be(:user_detail) { create(:user).user_detail }
|
||||
|
||||
it 'accepts a valid orcid username' do
|
||||
user_detail.orcid = '1234-1234-1234-1234'
|
||||
|
||||
expect(user_detail).to be_valid
|
||||
end
|
||||
|
||||
context 'when orcid id is wrong' do
|
||||
it 'throws an error when orcid username format is too long' do
|
||||
user_detail.orcid = '1234-1234-1234-1234-1234'
|
||||
|
||||
expect(user_detail).not_to be_valid
|
||||
expect(user_detail.errors.full_messages)
|
||||
.to match_array([_('Orcid must contain only a orcid ID.')])
|
||||
end
|
||||
|
||||
it 'throws an error when orcid username format is too short' do
|
||||
user_detail.orcid = '1234-1234'
|
||||
|
||||
expect(user_detail).not_to be_valid
|
||||
expect(user_detail.errors.full_messages)
|
||||
.to match_array([_('Orcid must contain only a orcid ID.')])
|
||||
end
|
||||
|
||||
it 'throws an error when orcid username format is letters' do
|
||||
user_detail.orcid = 'abcd-abcd-abcd-abcd'
|
||||
|
||||
expect(user_detail).not_to be_valid
|
||||
expect(user_detail.errors.full_messages)
|
||||
.to match_array([_('Orcid must contain only a orcid ID.')])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#location' do
|
||||
it { is_expected.to validate_length_of(:location).is_at_most(500) }
|
||||
end
|
||||
|
|
@ -423,6 +461,7 @@ RSpec.describe UserDetail, feature_category: :system_access do
|
|||
linkedin: 'linkedin',
|
||||
location: 'location',
|
||||
bluesky: 'did:plc:ewvi7nxzyoun6zhxrhs64oiz',
|
||||
orcid: '1234-1234-1234-1234',
|
||||
mastodon: '@robin@example.com',
|
||||
organization: 'organization',
|
||||
skype: 'skype',
|
||||
|
|
@ -447,6 +486,7 @@ RSpec.describe UserDetail, feature_category: :system_access do
|
|||
it_behaves_like 'prevents `nil` value', :linkedin
|
||||
it_behaves_like 'prevents `nil` value', :location
|
||||
it_behaves_like 'prevents `nil` value', :bluesky
|
||||
it_behaves_like 'prevents `nil` value', :orcid
|
||||
it_behaves_like 'prevents `nil` value', :mastodon
|
||||
it_behaves_like 'prevents `nil` value', :organization
|
||||
it_behaves_like 'prevents `nil` value', :skype
|
||||
|
|
|
|||
|
|
@ -150,6 +150,9 @@ RSpec.describe User, feature_category: :user_profile do
|
|||
it { is_expected.to delegate_method(:skype).to(:user_detail).allow_nil }
|
||||
it { is_expected.to delegate_method(:skype=).to(:user_detail).with_arguments(:args).allow_nil }
|
||||
|
||||
it { is_expected.to delegate_method(:orcid).to(:user_detail).allow_nil }
|
||||
it { is_expected.to delegate_method(:orcid=).to(:user_detail).with_arguments(:args).allow_nil }
|
||||
|
||||
it { is_expected.to delegate_method(:website_url).to(:user_detail).allow_nil }
|
||||
it { is_expected.to delegate_method(:website_url=).to(:user_detail).with_arguments(:args).allow_nil }
|
||||
|
||||
|
|
|
|||
|
|
@ -21,8 +21,7 @@ RSpec.shared_examples 'permission level for issue mutation is correctly verified
|
|||
)
|
||||
end
|
||||
|
||||
# TODO: .reload can be removed after the migration https://gitlab.com/gitlab-org/gitlab/-/issues/497857
|
||||
let(:expected) { issue_attributes(issue.reload) }
|
||||
let(:expected) { issue_attributes(issue) }
|
||||
|
||||
shared_examples_for 'when the user does not have access to the resource' do |raise_for_assigned_and_author|
|
||||
before do
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ RSpec.describe 'devise/shared/_footer', feature_category: :system_access do
|
|||
end
|
||||
|
||||
it { is_expected.to have_link(_('About GitLab'), href: ApplicationHelper.promo_url) }
|
||||
it { is_expected.to have_link(_('Community forum'), href: ApplicationHelper.community_forum) }
|
||||
it { is_expected.to have_link(_('GitLab community forum'), href: ApplicationHelper.community_forum) }
|
||||
|
||||
context 'when one trust is enabled' do
|
||||
before do
|
||||
|
|
|
|||
|
|
@ -115,27 +115,6 @@ RSpec.describe Gitlab::JiraImport::ImportIssueWorker, feature_category: :importe
|
|||
expect(issue.work_item_type_id).to eq(issue_type.id)
|
||||
end
|
||||
|
||||
context 'when legacy correct_work_item_type_id was part of the attributes (backward compatibility)' do
|
||||
let(:issue_type) { ::WorkItems::Type.default_issue_type }
|
||||
# At the moment, both id and correct_id columns have the same value in the work_item_types table
|
||||
let(:correct_work_item_type_id) { issue_type.id }
|
||||
let(:issue_attrs) do
|
||||
Gitlab::JiraImport::IssueSerializer.new(
|
||||
project,
|
||||
jira_issue,
|
||||
user.id,
|
||||
issue_type,
|
||||
params
|
||||
).execute.except(:work_item_type_id).merge(correct_work_item_type_id: correct_work_item_type_id)
|
||||
end
|
||||
|
||||
it 'creates an issue with the correct type' do
|
||||
issue = Issue.last
|
||||
|
||||
expect(issue.work_item_type_id).to eq(issue_type.id)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when assignee_ids is nil' do
|
||||
let(:assignee_ids) { nil }
|
||||
|
||||
|
|
|
|||
|
|
@ -107,6 +107,108 @@ RSpec.describe Packages::CleanupPackageFileWorker, type: :worker, feature_catego
|
|||
.and change { Packages::Package.count }.by(0)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a Conan package file' do
|
||||
let_it_be(:package) { create(:conan_package, without_package_files: true) }
|
||||
let_it_be(:package_file) { create(:conan_package_file, :conan_package_info, :pending_destruction, package: package) }
|
||||
let_it_be(:package_file_2) { create(:conan_package_file, package: package) }
|
||||
let_it_be(:recipe_revision) { package.conan_recipe_revisions.first }
|
||||
let_it_be(:package_reference) { package.conan_package_references.first }
|
||||
let_it_be(:package_revision) { package.conan_package_revisions.first }
|
||||
|
||||
context 'when deleting recipe revision' do
|
||||
context 'when the recipe revision is orphan but there are other recipe revisions' do
|
||||
let_it_be(:recipe_revision2) { create(:conan_recipe_revision, package: package) }
|
||||
let_it_be(:other_metadata) do
|
||||
create(:conan_file_metadatum, recipe_revision: recipe_revision2, package_file: package_file_2)
|
||||
end
|
||||
|
||||
it 'deletes the recipe revision and its dependent objects' do
|
||||
expect { subject }.to change { Packages::PackageFile.count }.by(-1)
|
||||
.and change { Packages::Conan::RecipeRevision.count }.by(-1)
|
||||
.and change { Packages::Conan::PackageReference.count }.by(-1)
|
||||
.and change { Packages::Conan::PackageRevision.count }.by(-1)
|
||||
.and not_change { Packages::Conan::Package.count }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the recipe revision is not orphan' do
|
||||
let_it_be(:other_metadata) do
|
||||
create(:conan_file_metadatum, recipe_revision: recipe_revision, package_file: package_file_2)
|
||||
end
|
||||
|
||||
it 'does not delete the recipe revision' do
|
||||
expect { subject }.to change { Packages::PackageFile.count }.by(-1)
|
||||
.and not_change { Packages::Conan::RecipeRevision.count }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when deleting package reference' do
|
||||
context 'when the package reference is orphan but there are other package references' do
|
||||
let_it_be(:package_reference2) { create(:conan_package_reference, package: package, recipe_revision: recipe_revision) }
|
||||
let_it_be(:package_revision2) { create(:conan_package_revision, package: package, package_reference: package_reference2) }
|
||||
let_it_be(:other_metadata) do
|
||||
create(:conan_file_metadatum, recipe_revision: recipe_revision, package_reference: package_reference2,
|
||||
package_revision: package_revision2, package_file: package_file_2, conan_file_type: 'package_file')
|
||||
end
|
||||
|
||||
it 'deletes the package reference and its dependent package revision' do
|
||||
expect { subject }.to change { Packages::PackageFile.count }.by(-1)
|
||||
.and change { Packages::Conan::PackageReference.count }.by(-1)
|
||||
.and change { Packages::Conan::PackageRevision.count }.by(-1)
|
||||
.and not_change { Packages::Conan::RecipeRevision.count }
|
||||
.and not_change { Packages::Conan::Package.count }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the package reference is still referenced by other package files' do
|
||||
let_it_be(:other_metadata) do
|
||||
create(:conan_file_metadatum,
|
||||
conan_file_type: 'package_file',
|
||||
recipe_revision: recipe_revision,
|
||||
package_reference: package_reference,
|
||||
package_revision: create(:conan_package_revision, package: package, package_reference: package_reference),
|
||||
package_file: package_file_2)
|
||||
end
|
||||
|
||||
it 'does not delete the package reference' do
|
||||
expect { subject }.to change { Packages::PackageFile.count }.by(-1)
|
||||
.and not_change { Packages::Conan::PackageReference.count }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when deleting package revision' do
|
||||
context 'when the package revision is orphan but there are other package revisions' do
|
||||
let_it_be(:package_revision2) { create(:conan_package_revision, package: package) }
|
||||
let_it_be(:other_metadata) do
|
||||
create(:conan_file_metadatum, recipe_revision: recipe_revision, package_reference: package_reference,
|
||||
package_revision: package_revision2, conan_file_type: 'package_file', package_file: package_file_2)
|
||||
end
|
||||
|
||||
it 'deletes the package revision' do
|
||||
expect { subject }.to change { Packages::PackageFile.count }.by(-1)
|
||||
.and change { Packages::Conan::PackageRevision.count }.by(-1)
|
||||
.and not_change { Packages::Conan::RecipeRevision.count }
|
||||
.and not_change { Packages::Conan::PackageReference.count }
|
||||
.and not_change { Packages::Conan::Package.count }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the package revision is still referenced by other package files' do
|
||||
let_it_be(:other_metadata) do
|
||||
create(:conan_file_metadatum, conan_file_type: 'package_file', recipe_revision: recipe_revision,
|
||||
package_reference: package_reference, package_revision: package_revision, package_file: package_file_2)
|
||||
end
|
||||
|
||||
it 'does not delete the package revision' do
|
||||
expect { subject }.to change { Packages::PackageFile.count }.by(-1)
|
||||
.and not_change { Packages::Conan::PackageRevision.count }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#max_running_jobs' do
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ require (
|
|||
github.com/jpillora/backoff v1.0.0
|
||||
github.com/mitchellh/copystructure v1.2.0
|
||||
github.com/prometheus/client_golang v1.21.1
|
||||
github.com/redis/go-redis/v9 v9.7.3
|
||||
github.com/redis/go-redis/v9 v9.8.0
|
||||
github.com/sebest/xff v0.0.0-20210106013422-671bd2870b3a
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/sony/gobreaker/v2 v2.1.0
|
||||
|
|
|
|||
|
|
@ -544,8 +544,8 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg
|
|||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||
github.com/prometheus/prometheus v0.54.0 h1:6+VmEkohHcofl3W5LyRlhw1Lfm575w/aX6ZFyVAmzM0=
|
||||
github.com/prometheus/prometheus v0.54.0/go.mod h1:xlLByHhk2g3ycakQGrMaU8K7OySZx98BzeCR99991NY=
|
||||
github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM=
|
||||
github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA=
|
||||
github.com/redis/go-redis/v9 v9.8.0 h1:q3nRvjrlge/6UD7eTu/DSg2uYiU2mCL0G/uzBWqhicI=
|
||||
github.com/redis/go-redis/v9 v9.8.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw=
|
||||
github.com/redis/rueidis v1.0.19 h1:s65oWtotzlIFN8eMPhyYwxlwLR1lUdhza2KtWprKYSo=
|
||||
github.com/redis/rueidis v1.0.19/go.mod h1:8B+r5wdnjwK3lTFml5VtxjzGOQAC+5UmujoD12pDrEo=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
|
|
|
|||
Loading…
Reference in New Issue