Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
1cc5b352a3
commit
9d2ebf5c7a
|
|
@ -6,7 +6,7 @@ workflow:
|
|||
|
||||
include:
|
||||
- local: .gitlab/ci/version.yml
|
||||
- component: "gitlab.com/gitlab-org/quality/pipeline-common/allure-report@8.21.0"
|
||||
- component: "gitlab.com/gitlab-org/quality/pipeline-common/allure-report@8.22.0"
|
||||
inputs:
|
||||
job_name: "e2e-test-report"
|
||||
job_stage: "report"
|
||||
|
|
@ -16,7 +16,7 @@ include:
|
|||
gitlab_auth_token_variable_name: "PROJECT_TOKEN_FOR_CI_SCRIPTS_API_USAGE"
|
||||
allure_job_name: "${QA_RUN_TYPE}"
|
||||
- project: gitlab-org/quality/pipeline-common
|
||||
ref: 8.21.0
|
||||
ref: 8.22.0
|
||||
file:
|
||||
- /ci/base.gitlab-ci.yml
|
||||
- /ci/knapsack-report.yml
|
||||
|
|
|
|||
|
|
@ -18,4 +18,4 @@ variables:
|
|||
# Retry failed specs in separate process
|
||||
QA_RETRY_FAILED_SPECS: "true"
|
||||
# helm chart ref used by test-on-cng pipeline
|
||||
GITLAB_HELM_CHART_REF: "e7f459ab671d8fdaecddd34c739e3d53c498bae2"
|
||||
GITLAB_HELM_CHART_REF: "3466c297acf5efa6de6bdfaa3c12b696041faa02"
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ export default {
|
|||
:reviewers="reviewers"
|
||||
:loading-reviewers="loadingReviewers"
|
||||
@request-review="(params) => $emit('request-review', params)"
|
||||
@remove-reviewer="(params) => $emit('remove-reviewer', params)"
|
||||
/>
|
||||
<approval-rules-wrapper :reviewers="reviewers" />
|
||||
</gl-drawer>
|
||||
|
|
|
|||
|
|
@ -83,10 +83,12 @@ export default {
|
|||
</div>
|
||||
<uncollapsed-reviewer-list
|
||||
v-else-if="reviewers.length"
|
||||
:is-editable="userPermissions.adminMergeRequest"
|
||||
:root-path="relativeUrlRoot"
|
||||
:users="reviewers"
|
||||
issuable-type="merge_request"
|
||||
@request-review="(params) => $emit('request-review', params)"
|
||||
@remove-reviewer="(params) => $emit('remove-reviewer', params)"
|
||||
/>
|
||||
<gl-empty-state v-else :svg-path="$options.noReviewersAssignedSvg" :svg-height="70">
|
||||
<template #description>
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ export default {
|
|||
<reviewer-drawer
|
||||
:open="drawerOpen"
|
||||
@request-review="(params) => $emit('request-review', params)"
|
||||
@remove-reviewer="(data) => $emit('remove-reviewer', data)"
|
||||
@close="toggleDrawerOpen(false)"
|
||||
/>
|
||||
</mounting-portal>
|
||||
|
|
|
|||
|
|
@ -51,6 +51,9 @@ export default {
|
|||
requestReview(data) {
|
||||
this.$emit('request-review', data);
|
||||
},
|
||||
removeReviewer(data) {
|
||||
this.$emit('remove-reviewer', data);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -84,6 +87,7 @@ export default {
|
|||
:root-path="rootPath"
|
||||
:issuable-type="issuableType"
|
||||
@request-review="requestReview"
|
||||
@remove-reviewer="removeReviewer"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import Vue from 'vue';
|
|||
import { createAlert } from '~/alert';
|
||||
import { TYPE_ISSUE } from '~/issues/constants';
|
||||
import { __ } from '~/locale';
|
||||
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
|
||||
import { isGid, getIdFromGraphQLId } from '~/graphql_shared/utils';
|
||||
import { fetchUserCounts } from '~/super_sidebar/user_counts_fetch';
|
||||
import eventHub from '../../event_hub';
|
||||
import getMergeRequestReviewersQuery from '../../queries/get_merge_request_reviewers.query.graphql';
|
||||
|
|
@ -166,6 +166,17 @@ export default {
|
|||
requestReview(data) {
|
||||
this.mediator.requestReview(data);
|
||||
},
|
||||
async removeReviewerById(event) {
|
||||
const userId = isGid(event.userId) ? getIdFromGraphQLId(event.userId) : event.userId;
|
||||
this.store.reviewers = this.store.reviewers.filter((user) => user.id !== userId);
|
||||
try {
|
||||
await this.saveReviewers();
|
||||
} catch (error) {
|
||||
createAlert(__('Unable to remove a reviewer at the moment, try again later'), { error });
|
||||
} finally {
|
||||
event.done();
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -177,6 +188,7 @@ export default {
|
|||
:loading="isLoading"
|
||||
:editable="canUpdate"
|
||||
@request-review="requestReview"
|
||||
@remove-reviewer="removeReviewerById"
|
||||
/>
|
||||
<reviewers
|
||||
v-if="!initialLoading"
|
||||
|
|
@ -187,6 +199,7 @@ export default {
|
|||
class="gl-pt-2"
|
||||
@request-review="requestReview"
|
||||
@assign-self="reviewBySelf"
|
||||
@remove-reviewer="removeReviewerById"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ const REVIEW_STATE_ICONS = {
|
|||
export default {
|
||||
i18n: {
|
||||
reRequestReview: __('Re-request review'),
|
||||
removeReviewer: s__('MergeRequest|Remove reviewer'),
|
||||
},
|
||||
components: {
|
||||
GlButton,
|
||||
|
|
@ -61,6 +62,11 @@ export default {
|
|||
required: false,
|
||||
default: TYPE_ISSUE,
|
||||
},
|
||||
isEditable: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
|
@ -112,7 +118,13 @@ export default {
|
|||
this.loadingStates[userId] = LOADING_STATE;
|
||||
this.$emit('request-review', { userId, callback: this.requestReviewComplete });
|
||||
},
|
||||
|
||||
removeReviewer(userId) {
|
||||
this.loadingStates[userId] = LOADING_STATE;
|
||||
this.$emit('remove-reviewer', {
|
||||
userId,
|
||||
callback: () => this.requestRemovalComplete(userId),
|
||||
});
|
||||
},
|
||||
requestReviewComplete(userId, success) {
|
||||
if (success) {
|
||||
this.loadingStates[userId] = SUCCESS_STATE;
|
||||
|
|
@ -124,6 +136,9 @@ export default {
|
|||
this.loadingStates[userId] = null;
|
||||
}
|
||||
},
|
||||
requestRemovalComplete(userId) {
|
||||
delete this.loadingStates[userId];
|
||||
},
|
||||
reviewStateIcon(user) {
|
||||
if (user.mergeRequestInteraction.approved) {
|
||||
return {
|
||||
|
|
@ -201,6 +216,20 @@ export default {
|
|||
data-testid="reviewer-state-icon"
|
||||
/>
|
||||
</span>
|
||||
<span v-if="isEditable" class="gl-inline-flex gl-h-6 gl-w-6">
|
||||
<gl-button
|
||||
v-gl-tooltip.top.viewport
|
||||
:title="$options.i18n.removeReviewer"
|
||||
:aria-label="$options.i18n.removeReviewer"
|
||||
:loading="loadingStates[user.id] === $options.LOADING_STATE"
|
||||
class="gl-float-right gl-ml-2 !gl-text-subtle"
|
||||
size="small"
|
||||
icon="close"
|
||||
variant="link"
|
||||
data-testid="remove-request-button"
|
||||
@click="removeReviewer(user.id)"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -510,6 +510,7 @@ export default {
|
|||
class="js-assignee gl-mb-5"
|
||||
:can-update="canUpdate"
|
||||
:full-path="fullPath"
|
||||
:is-group="isGroup"
|
||||
:work-item-id="workItemId"
|
||||
:assignees="workItemAssignees.assignees.nodes"
|
||||
:participants="workItemParticipantNodes"
|
||||
|
|
@ -525,6 +526,7 @@ export default {
|
|||
class="js-labels gl-mb-5"
|
||||
:can-update="canUpdate"
|
||||
:full-path="fullPath"
|
||||
:is-group="isGroup"
|
||||
:work-item-id="workItemId"
|
||||
:work-item-iid="workItemIid"
|
||||
:work-item-type="selectedWorkItemTypeName"
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ export default {
|
|||
GlAlert,
|
||||
},
|
||||
directives: { SafeHtml },
|
||||
inject: ['isGroup'],
|
||||
props: {
|
||||
value: {
|
||||
type: Array,
|
||||
|
|
@ -38,6 +37,11 @@ export default {
|
|||
type: String,
|
||||
required: true,
|
||||
},
|
||||
isGroup: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
childrenType: {
|
||||
type: String,
|
||||
required: false,
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ export default {
|
|||
UncollapsedAssigneeList,
|
||||
},
|
||||
mixins: [Tracking.mixin()],
|
||||
inject: ['isGroup'],
|
||||
props: {
|
||||
fullPath: {
|
||||
type: String,
|
||||
|
|
@ -55,6 +54,11 @@ export default {
|
|||
required: false,
|
||||
default: false,
|
||||
},
|
||||
isGroup: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
participants: {
|
||||
type: Array,
|
||||
required: false,
|
||||
|
|
|
|||
|
|
@ -60,6 +60,11 @@ export default {
|
|||
type: String,
|
||||
required: true,
|
||||
},
|
||||
isGroup: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
workItem: {
|
||||
type: Object,
|
||||
required: true,
|
||||
|
|
@ -185,6 +190,7 @@ export default {
|
|||
class="js-assignee gl-mb-5"
|
||||
:can-update="canUpdate"
|
||||
:full-path="fullPath"
|
||||
:is-group="isGroup"
|
||||
:work-item-id="workItem.id"
|
||||
:assignees="workItemAssignees.assignees.nodes"
|
||||
:participants="workItemParticipants"
|
||||
|
|
@ -203,6 +209,7 @@ export default {
|
|||
class="js-labels gl-mb-5"
|
||||
:can-update="canUpdate"
|
||||
:full-path="fullPath"
|
||||
:is-group="isGroup"
|
||||
:work-item-id="workItem.id"
|
||||
:work-item-iid="workItem.iid"
|
||||
:work-item-type="workItemType"
|
||||
|
|
@ -314,6 +321,7 @@ export default {
|
|||
:parent="workItemParent"
|
||||
:has-parent="hasParent"
|
||||
:group-path="groupPath"
|
||||
:is-group="isGroup"
|
||||
@error="$emit('error', $event)"
|
||||
/>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { s__ } from '~/locale';
|
|||
import { getParameterByName, updateHistory, setUrlParams } from '~/lib/utils/url_utility';
|
||||
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
||||
import { convertToGraphQLId, getIdFromGraphQLId } from '~/graphql_shared/utils';
|
||||
import { TYPENAME_WORK_ITEM } from '~/graphql_shared/constants';
|
||||
import { TYPENAME_GROUP, TYPENAME_WORK_ITEM } from '~/graphql_shared/constants';
|
||||
import { isLoggedIn } from '~/lib/utils/common_utils';
|
||||
import { WORKSPACE_PROJECT } from '~/issues/constants';
|
||||
import {
|
||||
|
|
@ -252,6 +252,9 @@ export default {
|
|||
isDiscussionLocked() {
|
||||
return this.workItemNotes?.discussionLocked;
|
||||
},
|
||||
isGroupWorkItem() {
|
||||
return this.workItem.namespace?.id.includes(TYPENAME_GROUP);
|
||||
},
|
||||
workItemsAlphaEnabled() {
|
||||
return this.glFeatures.workItemsAlpha;
|
||||
},
|
||||
|
|
@ -701,6 +704,7 @@ export default {
|
|||
<work-item-attributes-wrapper
|
||||
:class="{ 'gl-top-3': isDrawer }"
|
||||
:full-path="workItemFullPath"
|
||||
:is-group="isGroupWorkItem"
|
||||
:work-item="workItem"
|
||||
:group-path="groupPath"
|
||||
@error="updateError = $event"
|
||||
|
|
@ -718,6 +722,7 @@ export default {
|
|||
<work-item-tree
|
||||
v-if="showWorkItemTree"
|
||||
:full-path="workItemFullPath"
|
||||
:is-group="isGroupWorkItem"
|
||||
:work-item-type="workItemType"
|
||||
:parent-work-item-type="workItem.workItemType.name"
|
||||
:work-item-id="workItem.id"
|
||||
|
|
@ -734,6 +739,7 @@ export default {
|
|||
/>
|
||||
<work-item-relationships
|
||||
v-if="workItemLinkedItems"
|
||||
:is-group="isGroupWorkItem"
|
||||
:work-item-id="workItem.id"
|
||||
:work-item-iid="workItemIid"
|
||||
:work-item-full-path="workItemFullPath"
|
||||
|
|
|
|||
|
|
@ -33,12 +33,17 @@ export default {
|
|||
WorkItemSidebarDropdownWidget,
|
||||
},
|
||||
mixins: [Tracking.mixin()],
|
||||
inject: ['canAdminLabel', 'isGroup', 'issuesListPath', 'labelsManagePath'],
|
||||
inject: ['canAdminLabel', 'issuesListPath', 'labelsManagePath'],
|
||||
props: {
|
||||
fullPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
isGroup: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
workItemId: {
|
||||
type: String,
|
||||
required: true,
|
||||
|
|
|
|||
|
|
@ -314,6 +314,7 @@ export default {
|
|||
data-testid="add-links-form"
|
||||
:full-path="fullPath"
|
||||
:full-name="workItem.namespace.fullName"
|
||||
:is-group="false"
|
||||
:issuable-gid="issuableGid"
|
||||
:work-item-iid="iid"
|
||||
:children-ids="childrenIds"
|
||||
|
|
|
|||
|
|
@ -36,12 +36,17 @@ export default {
|
|||
WorkItemProjectsListbox,
|
||||
},
|
||||
mixins: [glFeatureFlagsMixin()],
|
||||
inject: ['hasIterationsFeature', 'isGroup'],
|
||||
inject: ['hasIterationsFeature'],
|
||||
props: {
|
||||
fullPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
isGroup: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
issuableGid: {
|
||||
type: String,
|
||||
required: false,
|
||||
|
|
@ -450,6 +455,7 @@ export default {
|
|||
<work-item-token-input
|
||||
v-model="workItemsToAdd"
|
||||
:is-create-form="isCreateForm"
|
||||
:is-group="isGroup"
|
||||
:parent-work-item-id="issuableGid"
|
||||
:children-type="childrenType"
|
||||
:children-ids="childrenIds"
|
||||
|
|
|
|||
|
|
@ -44,6 +44,11 @@ export default {
|
|||
type: String,
|
||||
required: true,
|
||||
},
|
||||
isGroup: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
workItemType: {
|
||||
type: String,
|
||||
required: true,
|
||||
|
|
@ -292,6 +297,7 @@ export default {
|
|||
data-testid="add-tree-form"
|
||||
:full-path="fullPath"
|
||||
:full-name="workItemNamespaceName"
|
||||
:is-group="isGroup"
|
||||
:issuable-gid="workItemId"
|
||||
:work-item-iid="workItemIid"
|
||||
:form-type="formType"
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ export default {
|
|||
GlPopover,
|
||||
WorkItemSidebarDropdownWidget,
|
||||
},
|
||||
inject: ['fullPath', 'isGroup'],
|
||||
inject: ['fullPath'],
|
||||
props: {
|
||||
workItemId: {
|
||||
type: String,
|
||||
|
|
@ -69,6 +69,11 @@ export default {
|
|||
required: false,
|
||||
default: false,
|
||||
},
|
||||
isGroup: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -24,6 +24,11 @@ export default {
|
|||
WorkItemTokenInput,
|
||||
},
|
||||
props: {
|
||||
isGroup: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
workItemId: {
|
||||
type: String,
|
||||
required: false,
|
||||
|
|
@ -205,6 +210,7 @@ export default {
|
|||
:children-ids="childrenIds"
|
||||
:are-work-items-to-add-valid="areWorkItemsToAddValid"
|
||||
:full-path="workItemFullPath"
|
||||
:is-group="isGroup"
|
||||
:max-selection-limit="maxWorkItems"
|
||||
@searching="searchInProgress = $event"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -27,6 +27,11 @@ export default {
|
|||
WorkItemMoreActions,
|
||||
},
|
||||
props: {
|
||||
isGroup: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
workItemId: {
|
||||
type: String,
|
||||
required: false,
|
||||
|
|
@ -227,6 +232,7 @@ export default {
|
|||
|
||||
<template #form>
|
||||
<work-item-add-relationship-form
|
||||
:is-group="isGroup"
|
||||
:work-item-id="workItemId"
|
||||
:work-item-iid="workItemIid"
|
||||
:work-item-full-path="workItemFullPath"
|
||||
|
|
|
|||
|
|
@ -235,7 +235,7 @@
|
|||
z-index: 1;
|
||||
position: relative;
|
||||
padding: $gl-padding-4 0;
|
||||
|
||||
|
||||
&.opened {
|
||||
color: $green-500;
|
||||
}
|
||||
|
|
@ -243,7 +243,7 @@
|
|||
&.closed {
|
||||
color: $blue-500;
|
||||
}
|
||||
|
||||
|
||||
svg {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
|
@ -270,17 +270,17 @@
|
|||
}
|
||||
|
||||
.assignee-grid {
|
||||
grid-template-areas: ' attention user';
|
||||
grid-template-areas: 'attention user';
|
||||
grid-template-columns: min-content 1fr;
|
||||
}
|
||||
|
||||
.reviewer-grid {
|
||||
grid-template-areas: ' user approval rerequest';
|
||||
grid-template-columns: 1fr min-content min-content;
|
||||
grid-template-areas: 'user approval rerequest remove';
|
||||
grid-template-columns: 1fr;
|
||||
|
||||
&.attention-requests {
|
||||
grid-template-areas: ' attention user approval';
|
||||
grid-template-columns: min-content 1fr min-content;
|
||||
grid-template-areas: 'attention user approval remove';
|
||||
grid-template-columns: auto 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,11 +8,17 @@ module Packages
|
|||
end
|
||||
|
||||
def execute!(package_name, package_version)
|
||||
project
|
||||
.packages
|
||||
.generic
|
||||
.installable
|
||||
.by_name_and_version!(package_name, package_version)
|
||||
if Feature.enabled?(:generic_extract_generic_package_model, Feature.current_request)
|
||||
Packages::Generic::Package.for_projects(project)
|
||||
.installable
|
||||
.by_name_and_version!(package_name, package_version)
|
||||
else
|
||||
project
|
||||
.packages
|
||||
.generic
|
||||
.installable
|
||||
.by_name_and_version!(package_name, package_version)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
|||
|
|
@ -12,7 +12,16 @@ class ApplicationSetting < ApplicationRecord
|
|||
ignore_columns %i[repository_storages], remove_with: '16.8', remove_after: '2023-12-21'
|
||||
ignore_column :required_instance_ci_template, remove_with: '17.1', remove_after: '2024-05-10'
|
||||
ignore_column :sign_in_text_html, remove_with: '17.5', remove_after: '2024-10-17'
|
||||
ignore_columns %i[openai_api_key anthropic_api_key vertex_ai_credentials vertex_ai_access_token], remove_with: '17.3', remove_after: '2024-08-15'
|
||||
ignore_columns %i[
|
||||
encrypted_openai_api_key
|
||||
encrypted_openai_api_key_iv
|
||||
encrypted_anthropic_api_key
|
||||
encrypted_anthropic_api_key_iv
|
||||
encrypted_vertex_ai_credentials
|
||||
encrypted_vertex_ai_credentials_iv
|
||||
encrypted_vertex_ai_access_token
|
||||
encrypted_vertex_ai_access_token_iv
|
||||
], remove_with: '17.5', remove_after: '2024-09-19'
|
||||
ignore_columns %i[toggle_security_policy_custom_ci lock_toggle_security_policy_custom_ci], remove_with: '17.6', remove_after: '2024-10-17'
|
||||
|
||||
INSTANCE_REVIEW_MIN_USERS = 50
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Packages
|
||||
module Generic
|
||||
class Package < Packages::Package
|
||||
self.allow_legacy_sti_class = true
|
||||
|
||||
after_create_commit :publish_creation_event
|
||||
|
||||
validates :name, format: { with: Gitlab::Regex.generic_package_name_regex }
|
||||
validates :version, presence: true, format: { with: Gitlab::Regex.generic_package_version_regex }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -35,7 +35,9 @@ class Packages::Package < ApplicationRecord
|
|||
belongs_to :project
|
||||
belongs_to :creator, class_name: 'User'
|
||||
|
||||
after_create_commit :publish_creation_event, if: :generic?
|
||||
# TODO: Remove with the rollout of the FF generic_extract_generic_package_model
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/issues/479933
|
||||
after_create_commit :publish_creation_event, if: -> { generic? && Feature.disabled?(:generic_extract_generic_package_model, Feature.current_request) }
|
||||
|
||||
# package_files must be destroyed by ruby code in order to properly remove carrierwave uploads and update project statistics
|
||||
has_many :package_files, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
|
||||
|
|
@ -71,7 +73,10 @@ class Packages::Package < ApplicationRecord
|
|||
|
||||
validate :npm_package_already_taken, if: :npm?
|
||||
|
||||
# TODO: Remove with the rollout of the FF generic_extract_generic_package_model
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/issues/479933
|
||||
validates :name, format: { with: Gitlab::Regex.generic_package_name_regex }, if: :generic?
|
||||
|
||||
validates :name, format: { with: Gitlab::Regex.npm_package_name_regex, message: Gitlab::Regex.npm_package_name_regex_message }, if: :npm?
|
||||
validates :name, format: { with: Gitlab::Regex.nuget_package_name_regex }, if: :nuget?
|
||||
validates :name, format: { with: Gitlab::Regex.terraform_module_package_name_regex }, if: :terraform_module?
|
||||
|
|
@ -81,6 +86,8 @@ class Packages::Package < ApplicationRecord
|
|||
validates :version, format: { with: Gitlab::Regex.semver_regex, message: Gitlab::Regex.semver_regex_message },
|
||||
if: -> { npm? || terraform_module? }
|
||||
|
||||
# TODO: Remove with the rollout of the FF generic_extract_generic_package_model
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/issues/479933
|
||||
validates :version,
|
||||
presence: true,
|
||||
format: { with: Gitlab::Regex.generic_package_version_regex },
|
||||
|
|
@ -183,16 +190,24 @@ class Packages::Package < ApplicationRecord
|
|||
|
||||
def self.inheritance_column = 'package_type'
|
||||
|
||||
def self.inheritance_column_to_class_map = {
|
||||
ml_model: 'Packages::MlModel::Package',
|
||||
golang: 'Packages::Go::Package',
|
||||
rubygems: 'Packages::Rubygems::Package',
|
||||
conan: 'Packages::Conan::Package',
|
||||
rpm: 'Packages::Rpm::Package',
|
||||
debian: 'Packages::Debian::Package',
|
||||
composer: 'Packages::Composer::Package',
|
||||
helm: 'Packages::Helm::Package'
|
||||
}.freeze
|
||||
def self.inheritance_column_to_class_map
|
||||
hash = {
|
||||
ml_model: 'Packages::MlModel::Package',
|
||||
golang: 'Packages::Go::Package',
|
||||
rubygems: 'Packages::Rubygems::Package',
|
||||
conan: 'Packages::Conan::Package',
|
||||
rpm: 'Packages::Rpm::Package',
|
||||
debian: 'Packages::Debian::Package',
|
||||
composer: 'Packages::Composer::Package',
|
||||
helm: 'Packages::Helm::Package'
|
||||
}
|
||||
|
||||
if Feature.enabled?(:generic_extract_generic_package_model, Feature.current_request)
|
||||
hash[:generic] = 'Packages::Generic::Package'
|
||||
end
|
||||
|
||||
hash
|
||||
end
|
||||
|
||||
def self.only_maven_packages_with_path(path, use_cte: false)
|
||||
if use_cte
|
||||
|
|
|
|||
|
|
@ -54,6 +54,11 @@ class ProjectSetting < ApplicationRecord
|
|||
Feature.enabled?(:legacy_open_source_license_available, type: :ops)
|
||||
end
|
||||
|
||||
# Checks if a given domain is already assigned to any existing project
|
||||
def self.unique_domain_exists?(domain)
|
||||
where(pages_unique_domain: domain).exists?
|
||||
end
|
||||
|
||||
def squash_enabled_by_default?
|
||||
%w[always default_on].include?(squash_option)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -39,10 +39,10 @@ module Projects
|
|||
else
|
||||
update_failed!
|
||||
end
|
||||
rescue ValidationError => e
|
||||
error(e.message)
|
||||
rescue ApiError => e
|
||||
error(e.message, status: :api_error)
|
||||
rescue ValidationError, Gitlab::Pages::UniqueDomainGenerationFailure => e
|
||||
error(e.message)
|
||||
end
|
||||
|
||||
def run_auto_devops_pipeline?
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
name: prompt_migration_explain_vulnerability
|
||||
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/475046
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/164210
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/480824
|
||||
milestone: '17.4'
|
||||
group: group::custom models
|
||||
type: experiment
|
||||
default_enabled: false
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
name: generic_extract_generic_package_model
|
||||
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/435829
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/163477
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/479933
|
||||
milestone: '17.4'
|
||||
group: group::package registry
|
||||
type: gitlab_com_derisk
|
||||
default_enabled: false
|
||||
|
|
@ -4,6 +4,7 @@ classes:
|
|||
- Packages::Composer::Package
|
||||
- Packages::Conan::Package
|
||||
- Packages::Debian::Package
|
||||
- Packages::Generic::Package
|
||||
- Packages::Go::Package
|
||||
- Packages::Helm::Package
|
||||
- Packages::MlModel::Package
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
table_name: security_policy_requirements
|
||||
classes:
|
||||
- ComplianceManagement::ComplianceFramework::SecurityPolicyRequirement
|
||||
feature_categories:
|
||||
- compliance_management
|
||||
description: Stores the mapping of compliance framework security policies and compliance requirements
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/163535
|
||||
milestone: '17.4'
|
||||
gitlab_schema: gitlab_main_cell
|
||||
sharding_key:
|
||||
namespace_id: namespaces
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CreateSecurityPolicyRequirements < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.4'
|
||||
|
||||
def change
|
||||
create_table :security_policy_requirements do |t| # rubocop:disable Migration/EnsureFactoryForTable -- https://gitlab.com/gitlab-org/gitlab/-/issues/468630
|
||||
t.bigint :compliance_framework_security_policy_id, null: false
|
||||
t.bigint :compliance_requirement_id, null: false
|
||||
t.bigint :namespace_id, null: false
|
||||
t.index :namespace_id
|
||||
t.index :compliance_requirement_id
|
||||
t.index [:compliance_framework_security_policy_id, :compliance_requirement_id], unique: true,
|
||||
name: :uniq_idx_security_policy_requirements_on_requirement_and_policy
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddFkToSecurityPolicyRequirementsOnNamespaceId < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.4'
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
add_concurrent_foreign_key :security_policy_requirements, :namespaces, column: :namespace_id, on_delete: :cascade,
|
||||
reverse_lock_order: true
|
||||
end
|
||||
|
||||
def down
|
||||
with_lock_retries do
|
||||
remove_foreign_key_if_exists :security_policy_requirements, column: :namespace_id, reverse_lock_order: true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddFkToSecurityPolicyRequirementsOnPolicyId < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.4'
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
add_concurrent_foreign_key :security_policy_requirements, :compliance_framework_security_policies,
|
||||
column: :compliance_framework_security_policy_id, on_delete: :cascade, reverse_lock_order: true
|
||||
end
|
||||
|
||||
def down
|
||||
with_lock_retries do
|
||||
remove_foreign_key_if_exists :security_policy_requirements, column: :compliance_framework_security_policy_id,
|
||||
reverse_lock_order: true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddFkToSecurityPolicyRequirementsOnRequirementId < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.4'
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
add_concurrent_foreign_key :security_policy_requirements, :compliance_requirements,
|
||||
column: :compliance_requirement_id, on_delete: :cascade, reverse_lock_order: true
|
||||
end
|
||||
|
||||
def down
|
||||
with_lock_retries do
|
||||
remove_foreign_key_if_exists :security_policy_requirements, column: :compliance_requirement_id,
|
||||
reverse_lock_order: true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
d4eb4ba8c8e1aff092c54710456eefc6aef515eada1241577c3ff9dbfe2ecc44
|
||||
|
|
@ -0,0 +1 @@
|
|||
e829816829772abaf14b6a66ebeebd1abd1420da3e56da80152f288e0d4eb160
|
||||
|
|
@ -0,0 +1 @@
|
|||
9963ffaf6bb629a07340bc4ebf09af6f034be4e408b904dfe889dab340ac9f86
|
||||
|
|
@ -0,0 +1 @@
|
|||
7e0c29fe5575e2dcc5e24bff41657ea3243f958566187a46d7c51207a1a8265d
|
||||
|
|
@ -17952,6 +17952,22 @@ CREATE SEQUENCE security_policy_project_links_id_seq
|
|||
|
||||
ALTER SEQUENCE security_policy_project_links_id_seq OWNED BY security_policy_project_links.id;
|
||||
|
||||
CREATE TABLE security_policy_requirements (
|
||||
id bigint NOT NULL,
|
||||
compliance_framework_security_policy_id bigint NOT NULL,
|
||||
compliance_requirement_id bigint NOT NULL,
|
||||
namespace_id bigint NOT NULL
|
||||
);
|
||||
|
||||
CREATE SEQUENCE security_policy_requirements_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
ALTER SEQUENCE security_policy_requirements_id_seq OWNED BY security_policy_requirements.id;
|
||||
|
||||
CREATE TABLE security_scans (
|
||||
id bigint NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
|
|
@ -22158,6 +22174,8 @@ ALTER TABLE ONLY security_policies ALTER COLUMN id SET DEFAULT nextval('security
|
|||
|
||||
ALTER TABLE ONLY security_policy_project_links ALTER COLUMN id SET DEFAULT nextval('security_policy_project_links_id_seq'::regclass);
|
||||
|
||||
ALTER TABLE ONLY security_policy_requirements ALTER COLUMN id SET DEFAULT nextval('security_policy_requirements_id_seq'::regclass);
|
||||
|
||||
ALTER TABLE ONLY security_scans ALTER COLUMN id SET DEFAULT nextval('security_scans_id_seq'::regclass);
|
||||
|
||||
ALTER TABLE ONLY security_training_providers ALTER COLUMN id SET DEFAULT nextval('security_training_providers_id_seq'::regclass);
|
||||
|
|
@ -24801,6 +24819,9 @@ ALTER TABLE ONLY security_policies
|
|||
ALTER TABLE ONLY security_policy_project_links
|
||||
ADD CONSTRAINT security_policy_project_links_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY security_policy_requirements
|
||||
ADD CONSTRAINT security_policy_requirements_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY security_scans
|
||||
ADD CONSTRAINT security_scans_pkey PRIMARY KEY (id);
|
||||
|
||||
|
|
@ -30023,6 +30044,10 @@ CREATE UNIQUE INDEX index_security_policy_project_links_on_project_and_policy ON
|
|||
|
||||
CREATE INDEX index_security_policy_project_links_on_project_id ON security_policy_project_links USING btree (project_id);
|
||||
|
||||
CREATE INDEX index_security_policy_requirements_on_compliance_requirement_id ON security_policy_requirements USING btree (compliance_requirement_id);
|
||||
|
||||
CREATE INDEX index_security_policy_requirements_on_namespace_id ON security_policy_requirements USING btree (namespace_id);
|
||||
|
||||
CREATE INDEX index_security_scans_for_non_purged_records ON security_scans USING btree (created_at, id) WHERE (status <> 6);
|
||||
|
||||
CREATE INDEX index_security_scans_on_created_at ON security_scans USING btree (created_at);
|
||||
|
|
@ -30945,6 +30970,8 @@ CREATE UNIQUE INDEX uniq_idx_packages_packages_on_project_id_name_version_ml_mod
|
|||
|
||||
CREATE UNIQUE INDEX uniq_idx_project_compliance_framework_on_project_framework ON project_compliance_framework_settings USING btree (project_id, framework_id);
|
||||
|
||||
CREATE UNIQUE INDEX uniq_idx_security_policy_requirements_on_requirement_and_policy ON security_policy_requirements USING btree (compliance_framework_security_policy_id, compliance_requirement_id);
|
||||
|
||||
CREATE UNIQUE INDEX uniq_idx_streaming_destination_id_and_namespace_id ON audit_events_streaming_instance_namespace_filters USING btree (external_streaming_destination_id, namespace_id);
|
||||
|
||||
CREATE UNIQUE INDEX uniq_idx_streaming_group_destination_id_and_namespace_id ON audit_events_streaming_group_namespace_filters USING btree (external_streaming_destination_id, namespace_id);
|
||||
|
|
@ -33357,6 +33384,9 @@ ALTER TABLE ONLY incident_management_timeline_events
|
|||
ALTER TABLE ONLY todos
|
||||
ADD CONSTRAINT fk_45054f9c45 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY security_policy_requirements
|
||||
ADD CONSTRAINT fk_458f7f5ad5 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY releases
|
||||
ADD CONSTRAINT fk_47fe2a0596 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
|
||||
|
||||
|
|
@ -33453,6 +33483,9 @@ ALTER TABLE ONLY project_export_jobs
|
|||
ALTER TABLE ONLY dependency_list_exports
|
||||
ADD CONSTRAINT fk_5b3d11e1ef FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;
|
||||
|
||||
ALTER TABLE ONLY security_policy_requirements
|
||||
ADD CONSTRAINT fk_5b4fae9635 FOREIGN KEY (compliance_requirement_id) REFERENCES compliance_requirements(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY user_broadcast_message_dismissals
|
||||
ADD CONSTRAINT fk_5c0cfb74ce FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
|
||||
|
|
@ -33990,6 +34023,9 @@ ALTER TABLE ONLY catalog_resource_versions
|
|||
ALTER TABLE ONLY bulk_import_entities
|
||||
ADD CONSTRAINT fk_b69fa2b2df FOREIGN KEY (bulk_import_id) REFERENCES bulk_imports(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY security_policy_requirements
|
||||
ADD CONSTRAINT fk_b6e48e3428 FOREIGN KEY (compliance_framework_security_policy_id) REFERENCES compliance_framework_security_policies(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY compliance_management_frameworks
|
||||
ADD CONSTRAINT fk_b74c45b71f FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,24 @@ LDAP synchronization updates user and group information for existing GitLab user
|
|||
|
||||
You can change when synchronization occurs.
|
||||
|
||||
## LDAP servers with rate limits
|
||||
|
||||
Some LDAP servers have rate limits configured.
|
||||
|
||||
GitLab queries the LDAP server once for every:
|
||||
|
||||
- User during the scheduled [user sync](#user-sync) process.
|
||||
- Group during the scheduled [group sync](#group-sync) process.
|
||||
|
||||
In some cases, more queries to the LDAP server may be triggered. For example, when a [group sync query returns a `memberuid` attribute](#queries).
|
||||
|
||||
If the LDAP server has a rate limit configured and that limit is reached during the:
|
||||
|
||||
- User sync process, the LDAP server responds with an error code and GitLab blocks that user.
|
||||
- Group sync process, the LDAP server responds with an error code and GitLab removes that user's group memberships.
|
||||
|
||||
You must consider your LDAP server's rate limits when configuring LDAP synchronization to prevent unwanted user blocks and group membership removals.
|
||||
|
||||
## User sync
|
||||
|
||||
> - Preventing LDAP user's profile name synchronization [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11336) in GitLab 15.11.
|
||||
|
|
@ -49,6 +67,9 @@ The process also updates the following user information:
|
|||
- SSH public keys if `sync_ssh_keys` is set.
|
||||
- Kerberos identity if Kerberos is enabled.
|
||||
|
||||
NOTE:
|
||||
If your LDAP server has a rate limit, that limit might be reached during the user sync process. Check the [rate limit documentation](#ldap-servers-with-rate-limits) for more information.
|
||||
|
||||
### Synchronize LDAP user's profile name
|
||||
|
||||
By default, GitLab synchronizes the LDAP user's profile name field.
|
||||
|
|
@ -184,6 +205,9 @@ be available to GitLab. For example, `group_base` could be
|
|||
`ou=groups,dc=example,dc=com`. In the configuration file, it looks like the
|
||||
following.
|
||||
|
||||
NOTE:
|
||||
If your LDAP server has a rate limit, that limit might be reached during the group sync process. Check the [rate limit documentation](#ldap-servers-with-rate-limits) for more information.
|
||||
|
||||
::Tabs
|
||||
|
||||
:::TabTitle Linux package (Omnibus)
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ DETAILS:
|
|||
**Status:** Beta
|
||||
|
||||
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/11180) as an [experiment](../../policy/experiment-beta-support.md#experiment) in GitLab 16.7 with [flags](../../administration/feature_flags.md) named `ci_data_ingestion_to_click_house` and `clickhouse_ci_analytics`. Disabled by default.
|
||||
> - [Enabled on GitLab.com, self-managed, and GitLab Dedicated](https://gitlab.com/gitlab-org/gitlab/-/issues/424866) in GitLab 16.10. Feature flags `ci_data_ingestion_to_click_house` and `clickhouse_ci_analytics` removed.
|
||||
> - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/424866) in GitLab 16.10. Feature flags `ci_data_ingestion_to_click_house` and `clickhouse_ci_analytics` removed.
|
||||
> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/424789) to [beta](../../policy/experiment-beta-support.md#beta) in GitLab 17.1.
|
||||
|
||||
WARNING:
|
||||
|
|
|
|||
|
|
@ -11,8 +11,7 @@ DETAILS:
|
|||
**Offering:** GitLab.com, Self-managed, GitLab Dedicated
|
||||
**Status:** Beta
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227345) in
|
||||
> GitLab 17.3 [with a flag](../../../administration/feature_flags.md) named `jacoco_coverage_reports`. Disabled by default.
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227345) in GitLab 17.3 [with a flag](../../../administration/feature_flags.md) named `jacoco_coverage_reports`. Disabled by default.
|
||||
|
||||
For JaCoCo coverage reports to work, you must generate a properly formatted [JaCoCo XML file](https://www.jacoco.org/jacoco/trunk/coverage/jacoco.xml)
|
||||
that provides [line coverage](https://www.eclemma.org/jacoco/trunk/doc/counters.html).
|
||||
|
|
|
|||
|
|
@ -155,6 +155,13 @@ Instead of **agnostic**, use **platform-independent** or **vendor-neutral**.
|
|||
|
||||
Use **AI**. Do not spell out **artificial intelligence**.
|
||||
|
||||
## AI Impact Dashboard
|
||||
|
||||
Use title case for **AI Impact Dashboard**.
|
||||
|
||||
On first mention on a page, use **GitLab Duo AI Impact Dashboard**.
|
||||
Thereafter, use **AI Impact Dashboard** by itself.
|
||||
|
||||
## AI-powered DevSecOps platform
|
||||
|
||||
If preceded by GitLab, capitalize **Platform**. For example, the GitLab AI-powered DevSecOps Platform.
|
||||
|
|
@ -428,12 +435,12 @@ Example:
|
|||
|
||||
- Use code completion to populate the file.
|
||||
|
||||
## Code explanation
|
||||
## Code Explanation
|
||||
|
||||
Use sentence case for **Code explanation**.
|
||||
Use title case for **Code Explanation**.
|
||||
|
||||
On first mention on a page, use **GitLab Duo Code explanation**.
|
||||
Thereafter, use **Code explanation** by itself.
|
||||
On first mention on a page, use **GitLab Duo Code Explanation**.
|
||||
Thereafter, use **Code Explanation** by itself.
|
||||
|
||||
## code generation
|
||||
|
||||
|
|
@ -452,12 +459,12 @@ Examples:
|
|||
- Use code generation to create code based on your comments.
|
||||
- Adjust your code generation results by adding code comments to your file.
|
||||
|
||||
## Code review summary
|
||||
## Code Review Summary
|
||||
|
||||
Use sentence case for **Code review summary**.
|
||||
Use title case for **Code Review Summary**.
|
||||
|
||||
On first mention on a page, use **GitLab Duo Code review summary**.
|
||||
Thereafter, use **Code review summary** by itself.
|
||||
On first mention on a page, use **GitLab Duo Code Review Summary**.
|
||||
Thereafter, use **Code Review Summary** by itself.
|
||||
|
||||
## Code Suggestions
|
||||
|
||||
|
|
@ -672,12 +679,12 @@ Use **inactive** or **off** instead.
|
|||
|
||||
Use **prevent** instead of **disallow**. ([Vale](../testing/vale.md) rule: [`Substitutions.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab_base/Substitutions.yml))
|
||||
|
||||
## Discussion summary
|
||||
## Discussion Summary
|
||||
|
||||
Use sentence case for **Discussion summary**.
|
||||
Use title case for **Discussion Summary**.
|
||||
|
||||
On first mention on a page, use **GitLab Duo Discussion summary**.
|
||||
Thereafter, use **Discussion summary** by itself.
|
||||
On first mention on a page, use **GitLab Duo Discussion Summary**.
|
||||
Thereafter, use **Discussion Summary** by itself.
|
||||
|
||||
## Docker-in-Docker, `dind`
|
||||
|
||||
|
|
@ -967,25 +974,34 @@ Do not use **Dedicated** by itself. Always use **GitLab Dedicated**.
|
|||
|
||||
Do not use **Duo** by itself. Always use **GitLab Duo**.
|
||||
|
||||
On first use on a page, use **GitLab Duo `<featurename>`**. As of Dec, 2023,
|
||||
On first use on a page, use **GitLab Duo `<featurename>`**. As of Aug, 2024,
|
||||
the following are the names of GitLab Duo features:
|
||||
|
||||
- GitLab Duo AI Impact Dashboard
|
||||
- GitLab Duo Chat
|
||||
- GitLab Duo Code Explanation
|
||||
- GitLab Duo Code Review Summary
|
||||
- GitLab Duo Code Suggestions
|
||||
- GitLab Duo Value stream forecasting
|
||||
- GitLab Duo Discussion summary
|
||||
- GitLab Duo Merge request summary
|
||||
- GitLab Duo Code review summary
|
||||
- GitLab Duo Code explanation
|
||||
- GitLab Duo Vulnerability explanation
|
||||
- GitLab Duo Vulnerability resolution
|
||||
- GitLab Duo Test generation
|
||||
- GitLab Duo for the CLI
|
||||
- GitLab Duo Root cause analysis
|
||||
- GitLab Duo Issue description generation
|
||||
- GitLab Duo Issue Description Generation
|
||||
- GitLab Duo Issue Discussion Summary
|
||||
- GitLab Duo Merge Commit Message Generation
|
||||
- GitLab Duo Merge Request Summary
|
||||
- GitLab Duo Product Analytics
|
||||
- GitLab Duo Root Cause Analysis
|
||||
- GitLab Duo Test Generation
|
||||
- GitLab Duo Vulnerability Explanation
|
||||
- GitLab Duo Vulnerability Resolution
|
||||
|
||||
After the first use, use the feature name without **GitLab Duo**.
|
||||
|
||||
## GitLab Duo Enterprise
|
||||
|
||||
Always use **GitLab Duo Enterprise** for the add-on. Do not use **Duo Enterprise** unless approved by legal.
|
||||
|
||||
You can use **the GitLab Duo Enterprise add-on** (with this capitalization) but you do not need to use **add-on**
|
||||
and should leave it off when you can.
|
||||
|
||||
## GitLab Duo Pro
|
||||
|
||||
Always use **GitLab Duo Pro** for the add-on. Do not use **Duo Pro** unless approved by legal.
|
||||
|
|
@ -1171,12 +1187,19 @@ Use lowercase for **issue**.
|
|||
|
||||
Use lowercase for **issue board**.
|
||||
|
||||
## Issue description generation
|
||||
## Issue Description Generation
|
||||
|
||||
Use sentence case for **Issue description generation**.
|
||||
Use title case for **Issue Description Generation**.
|
||||
|
||||
On first mention on a page, use **GitLab Duo Issue description generation**.
|
||||
Thereafter, use **Issue description generation** by itself.
|
||||
On first mention on a page, use **GitLab Duo Issue Description Generation**.
|
||||
Thereafter, use **Issue Description Generation** by itself.
|
||||
|
||||
## Issue Discussion Summary
|
||||
|
||||
Use title case for **Issue Discussion Summary**.
|
||||
|
||||
On first mention on a page, use **GitLab Duo Issue Discussion Summary**.
|
||||
Thereafter, use **Issue Discussion Summary** by itself.
|
||||
|
||||
## issue weights
|
||||
|
||||
|
|
@ -1387,6 +1410,13 @@ For **MB** and **GB**, follow the [Microsoft guidance](https://learn.microsoft.c
|
|||
When you add a [user account](#user-account) to a group or project,
|
||||
the user account becomes a **member**.
|
||||
|
||||
## Merge Commit Message Generation
|
||||
|
||||
Use title case for **Merge Commit Message Generation**.
|
||||
|
||||
On first mention on a page, use **GitLab Duo Merge Commit Message Generation**.
|
||||
Thereafter, use **Merge Commit Message Generation** by itself.
|
||||
|
||||
## merge request branch
|
||||
|
||||
Do not use **merge request branch**. See [branch](#branch).
|
||||
|
|
@ -1395,12 +1425,12 @@ Do not use **merge request branch**. See [branch](#branch).
|
|||
|
||||
Use lowercase for **merge requests**. If you use **MR** as the acronym, spell it out on first use.
|
||||
|
||||
## Merge request summary
|
||||
## Merge Request Summary
|
||||
|
||||
Use sentence case for **Merge request summary**.
|
||||
Use title case for **Merge Request Summary**.
|
||||
|
||||
On first mention on a page, use **GitLab Duo Merge request summary**.
|
||||
Thereafter, use **Merge request summary** by itself.
|
||||
On first mention on a page, use **GitLab Duo Merge Request Summary**.
|
||||
Thereafter, use **Merge Request Summary** by itself.
|
||||
|
||||
## milestones
|
||||
|
||||
|
|
@ -1829,12 +1859,12 @@ There are two types of roles: [custom](#custom-role) and [default](#default-role
|
|||
|
||||
Roles are not the same as [**access levels**](#access-level).
|
||||
|
||||
## Root cause analysis
|
||||
## Root Cause Analysis
|
||||
|
||||
Use sentence case for **Root cause analysis**.
|
||||
Use title case for **Root Cause Analysis**.
|
||||
|
||||
On first mention on a page, use **GitLab Duo Root cause analysis**.
|
||||
Thereafter, use **Root cause analysis** by itself.
|
||||
On first mention on a page, use **GitLab Duo Root Cause Analysis**.
|
||||
Thereafter, use **Root Cause Analysis** by itself.
|
||||
|
||||
## roll back
|
||||
|
||||
|
|
@ -2110,12 +2140,12 @@ talking about non-specific modules. For example:
|
|||
|
||||
- You can publish a Terraform module to your project's Terraform Module Registry.
|
||||
|
||||
## Test generation
|
||||
## Test Generation
|
||||
|
||||
Use sentence case for **Test generation**.
|
||||
Use title case for **Test Generation**.
|
||||
|
||||
On first mention on a page, use **GitLab Duo Test generation**.
|
||||
Thereafter, use **Test generation** by itself.
|
||||
On first mention on a page, use **GitLab Duo Test Generation**.
|
||||
Thereafter, use **Test Generation** by itself.
|
||||
|
||||
## text box
|
||||
|
||||
|
|
@ -2272,12 +2302,6 @@ For example:
|
|||
Do not use **utilize**. Use **use** instead. It's more succinct and easier for non-native English speakers to understand.
|
||||
([Vale](../testing/vale.md) rule: [`SubstitutionWarning.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab_base/SubstitutionWarning.yml))
|
||||
|
||||
## Value stream forecasting
|
||||
|
||||
Use sentence case for **Value stream forecasting**. On first mention on a page, use **GitLab Duo Value stream forecasting**.
|
||||
|
||||
Thereafter, use **Value stream forecasting** by itself.
|
||||
|
||||
## version, v
|
||||
|
||||
To describe versions of GitLab, use **GitLab `<version number>`**. For example:
|
||||
|
|
@ -2297,19 +2321,19 @@ Pay attention to spacing by the letter **v**. In semantic versioning, no space e
|
|||
|
||||
Do not use Latin abbreviations. Use **with**, **through**, or **by using** instead. ([Vale](../testing/vale.md) rule: [`LatinTerms.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab_base/LatinTerms.yml))
|
||||
|
||||
## Vulnerability resolution
|
||||
## Vulnerability Explanation
|
||||
|
||||
Use sentence case for **Vulnerability resolution**.
|
||||
Use title case for **Vulnerability Explanation**.
|
||||
|
||||
On first mention on a page, use **GitLab Duo Vulnerability resolution**.
|
||||
Thereafter, use **Vulnerability resolution** by itself.
|
||||
On first mention on a page, use **GitLab Duo Vulnerability Explanation**.
|
||||
Thereafter, use **Vulnerability Explanation** by itself.
|
||||
|
||||
## Vulnerability explanation
|
||||
## Vulnerability Resolution
|
||||
|
||||
Use sentence case for **Vulnerability explanation**.
|
||||
Use title case for **Vulnerability Resolution**.
|
||||
|
||||
On first mention on a page, use **GitLab Duo Vulnerability explanation**.
|
||||
Thereafter, use **Vulnerability explanation** by itself.
|
||||
On first mention on a page, use **GitLab Duo Vulnerability Resolution**.
|
||||
Thereafter, use **Vulnerability Resolution** by itself.
|
||||
|
||||
## we
|
||||
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ To add more languages to Code Suggestions:
|
|||
1. On the top bar, go to **Code > Settings > Extensions**.
|
||||
1. Search for **GitLab Workflow** in the list, then select **Manage** (**{settings}**) **> Extension Settings**.
|
||||
1. In your **User** settings, find
|
||||
**GitLab › Ai Assisted Code Suggestions: Additional Languages** and select **Add Item**.
|
||||
**GitLab › Duo Code Suggestions: Additional Languages** and select **Add Item**.
|
||||
1. In **Item**, add the language identifier, and select **OK**.
|
||||
|
||||
## Integrate with GitLab
|
||||
|
|
|
|||
|
|
@ -85,3 +85,23 @@ To request a limit increase to 1,048,576 bytes per minute, contact GitLab suppor
|
|||
## Data retention
|
||||
|
||||
GitLab has a retention limit of 30 days for all traces.
|
||||
|
||||
## Create an issue for a trace
|
||||
|
||||
You can create an issue to track any action taken to resolve or investigate a trace. To create an issue for a trace:
|
||||
|
||||
1. On the left sidebar, select **Search or go to** and find your project.
|
||||
1. Select **Monitor > Traces**.
|
||||
1. From the list of traces, select a trace.
|
||||
1. Select **Create issue**.
|
||||
|
||||
The issue is created in the selected project and pre-filled with information from the trace.
|
||||
You can edit the issue title and description.
|
||||
|
||||
## View issues related to a trace
|
||||
|
||||
1. On the left sidebar, select **Search or go to** and find your project.
|
||||
1. Select **Monitor > Traces**.
|
||||
1. From the list of traces, select a trace.
|
||||
1. Scroll to **Related issues**.
|
||||
1. Optional. To view the issue details, select an issue.
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ You are automatically enrolled in quarterly reconciliation if:
|
|||
You are excluded from quarterly reconciliation if you:
|
||||
|
||||
- Purchased your subscription from a reseller or another channel partner.
|
||||
- Purchased a multi-year subscription.
|
||||
- Purchased a subscription that is not a 12-month term (includes multi-year and non-standard length subscriptions).
|
||||
- Purchased your subscription with a purchasing order.
|
||||
- Are a public sector customer.
|
||||
- Have an offline environment and used a license file to activate your subscription.
|
||||
|
|
@ -91,12 +91,9 @@ If you are excluded from quarterly reconciliation and not on a free tier, your t
|
|||
|
||||
### Failed payment
|
||||
|
||||
If your credit card is declined during the reconciliation process, you receive an email with the subject `Your GitLab subscription failed to reconcile`.
|
||||
To resolve this issue, you must [update your payment information](customers_portal.md#set-a-default-payment-method).
|
||||
If your credit card is declined during the reconciliation process, you receive an email with the subject `Action required: Your GitLab subscription failed to reconcile`. To resolve this issue, you must:
|
||||
|
||||
1. Sign in to your account at `https://customers.gitlab.com`.
|
||||
1. On the left sidebar, select **Billing account settings**.
|
||||
1. Under **Payment methods**, select **Add new payment method**.
|
||||
1. To mark the new payment method as default, select **Edit** > **Default**.
|
||||
1. [Update your payment information](customers_portal.md#change-your-payment-method).
|
||||
1. [Set your chosen payment method as default](customers_portal.md#set-a-default-payment-method).
|
||||
|
||||
When the payment method is updated, reconciliation is retried automatically.
|
||||
|
|
|
|||
|
|
@ -574,28 +574,28 @@ To add another contact for your subscription, see [Add a secondary contact](../c
|
|||
|
||||
## Subscription expiry
|
||||
|
||||
When your license expires, GitLab locks down features, like Git pushes
|
||||
and issue creation. Then, your instance becomes read-only and
|
||||
an expiration message is displayed to all administrators.
|
||||
|
||||
Licenses expire at the start of the expiration date, 00:00 server time.
|
||||
|
||||
For GitLab self-managed instances, you have a 14-day grace period
|
||||
before this occurs.
|
||||
When your license expires, after a 14 day grace period:
|
||||
|
||||
For example, if a license has a start date of January 1, 2024 and an end date of January 1, 2025:
|
||||
- Your instance becomes read-only.
|
||||
- GitLab locks features, such as Git pushes and issue creation.
|
||||
- An expiration message is displayed to all administrators.
|
||||
|
||||
For example, if a license has an expiry date of January 1, 2025:
|
||||
|
||||
- It expires at 11:59:59 PM server time December 31, 2024.
|
||||
- It is considered expired from 12:00:00 AM server time January 1, 2025.
|
||||
- The grace period of 14 days starts at 12:00:00 AM server time January 1, 2025 and ends at 11:59:59 PM server time January 14, 2025.
|
||||
- The grace period of 14 days starts at 12:00:00 AM server time January 1, 2025
|
||||
and ends at 11:59:59 PM server time January 14, 2025.
|
||||
- Your instance becomes read-only at 12:00:00 AM server time January 15, 2025.
|
||||
|
||||
- To resume functionality, activate a new license.
|
||||
- To fall back to Free features, delete the expired license.
|
||||
After your license has expired:
|
||||
|
||||
## Activate a license file or key
|
||||
|
||||
If you have a license file or key, you can activate it [in the **Admin** area](../../administration/license_file.md#activate-gitlab-ee-with-a-license-file-or-key).
|
||||
- To resume functionality,
|
||||
[activate a new license](../../administration/license_file.md#activate-gitlab-ee-with-a-license-file-or-key).
|
||||
- To keep using Free tier features only,
|
||||
[delete the expired license](../../administration/license_file.md#remove-a-license).
|
||||
|
||||
## Storage
|
||||
|
||||
|
|
|
|||
|
|
@ -297,9 +297,8 @@ DETAILS:
|
|||
**Tier:** Ultimate
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/211387) in GitLab 13.5.
|
||||
> Expanded to include additional passthrough types of `file` and `raw` in GitLab 14.6.
|
||||
> - [Enabled](https://gitlab.com/gitlab-org/gitlab/-/issues/235359) support for overriding rules in
|
||||
> GitLab 14.8.
|
||||
> - Expanded to include additional passthrough types of `file` and `raw` in GitLab 14.6.
|
||||
> - [Enabled](https://gitlab.com/gitlab-org/gitlab/-/issues/235359) support for overriding rules in GitLab 14.8.
|
||||
> - [Enabled](https://gitlab.com/gitlab-org/gitlab/-/issues/336395) support for passthrough chains and included additional passthrough types of `git` and `url` in GitLab 17.2.
|
||||
|
||||
You can customize the behavior of pipeline secret detection by [creating a ruleset configuration file](#create-a-ruleset-configuration-file),
|
||||
|
|
|
|||
|
|
@ -11,8 +11,7 @@ DETAILS:
|
|||
**Offering:** GitLab.com
|
||||
**Status:** Beta
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/141127) in GitLab 16.10 [with a flag](../../../administration/feature_flags.md) named
|
||||
`google_cloud_support_feature_flag`. This feature is in [beta](../../../policy/experiment-beta-support.md).
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/141127) in GitLab 16.10 [with a flag](../../../administration/feature_flags.md) named `google_cloud_support_feature_flag`. This feature is in [beta](../../../policy/experiment-beta-support.md).
|
||||
> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/150472) in GitLab 17.1. Feature flag `google_cloud_support_feature_flag` removed.
|
||||
|
||||
This feature is in [beta](../../../policy/experiment-beta-support.md).
|
||||
|
|
@ -127,7 +126,7 @@ list-images:
|
|||
|
||||
```yaml
|
||||
list-images:
|
||||
image:
|
||||
image:
|
||||
name: gcr.io/go-containerregistry/crane:debug
|
||||
entrypoint: [""]
|
||||
identity: google_cloud
|
||||
|
|
@ -209,7 +208,7 @@ copy-image:
|
|||
|
||||
```yaml
|
||||
copy-image:
|
||||
image:
|
||||
image:
|
||||
name: gcr.io/go-containerregistry/crane:debug
|
||||
entrypoint: [""]
|
||||
identity: google_cloud
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ Prerequisites:
|
|||
from the Visual Studio Marketplace.
|
||||
1. Configure the extension following the
|
||||
[setup instructions](https://gitlab.com/gitlab-org/gitlab-vscode-extension#extension-settings).
|
||||
1. Enable the feature by toggling the `gitlab.aiAssistedCodeSuggestions.enabledSupportedLanguages` setting.
|
||||
1. Enable the feature by toggling the `gitlab.duoCodeSuggestions.enabledSupportedLanguages` setting.
|
||||
|
||||
:::TabTitle JetBrains IDEs
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ If you are a self-managed user, ensure that Code Suggestions for the [GitLab Web
|
|||
|
||||
1. On the left sidebar, select **Extensions > GitLab Workflow**.
|
||||
1. Select **Settings** (**{settings}**), and then select **Extension Settings**.
|
||||
1. In **GitLab > AI Assisted Code Suggestions**, select the **GitLab Duo Code Suggestions**
|
||||
1. In **GitLab > Duo Code Suggestions**, select the **GitLab Duo Code Suggestions**
|
||||
checkbox.
|
||||
|
||||
### View Code Suggestions logs
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ module Gitlab
|
|||
|
||||
override :validate_regex
|
||||
def validate_regex(value, default)
|
||||
return unless spec.key?(:regex)
|
||||
return unless spec.key?(:regex) && value.is_a?(String)
|
||||
|
||||
safe_regex = ::Gitlab::UntrustedRegexp.new(spec[:regex])
|
||||
|
||||
|
|
|
|||
|
|
@ -7,14 +7,14 @@ module Gitlab
|
|||
module Validators
|
||||
class SchemaValidator
|
||||
SUPPORTED_VERSIONS = {
|
||||
cluster_image_scanning: %w[15.0.0 15.0.1 15.0.2 15.0.4 15.0.5 15.0.6 15.0.7 15.1.0 15.1.1 15.1.2 15.1.3 15.1.4 15.2.0],
|
||||
container_scanning: %w[15.0.0 15.0.1 15.0.2 15.0.4 15.0.5 15.0.6 15.0.7 15.1.0 15.1.1 15.1.2 15.1.3 15.1.4 15.2.0],
|
||||
coverage_fuzzing: %w[15.0.0 15.0.1 15.0.2 15.0.4 15.0.5 15.0.6 15.0.7 15.1.0 15.1.1 15.1.2 15.1.3 15.1.4 15.2.0],
|
||||
dast: %w[15.0.0 15.0.1 15.0.2 15.0.4 15.0.5 15.0.6 15.0.7 15.1.0 15.1.1 15.1.2 15.1.3 15.1.4 15.2.0],
|
||||
api_fuzzing: %w[15.0.0 15.0.1 15.0.2 15.0.4 15.0.5 15.0.6 15.0.7 15.1.0 15.1.1 15.1.2 15.1.3 15.1.4 15.2.0],
|
||||
dependency_scanning: %w[15.0.0 15.0.1 15.0.2 15.0.4 15.0.5 15.0.6 15.0.7 15.1.0 15.1.1 15.1.2 15.1.3 15.1.4 15.2.0],
|
||||
sast: %w[15.0.0 15.0.1 15.0.2 15.0.4 15.0.5 15.0.6 15.0.7 15.1.0 15.1.1 15.1.2 15.1.3 15.1.4 15.2.0],
|
||||
secret_detection: %w[15.0.0 15.0.1 15.0.2 15.0.4 15.0.5 15.0.6 15.0.7 15.1.0 15.1.1 15.1.2 15.1.3 15.1.4 15.2.0]
|
||||
cluster_image_scanning: %w[15.0.0 15.0.1 15.0.2 15.0.4 15.0.5 15.0.6 15.0.7 15.1.0 15.1.1 15.1.2 15.1.3 15.1.4 15.2.0 15.2.1],
|
||||
container_scanning: %w[15.0.0 15.0.1 15.0.2 15.0.4 15.0.5 15.0.6 15.0.7 15.1.0 15.1.1 15.1.2 15.1.3 15.1.4 15.2.0 15.2.1],
|
||||
coverage_fuzzing: %w[15.0.0 15.0.1 15.0.2 15.0.4 15.0.5 15.0.6 15.0.7 15.1.0 15.1.1 15.1.2 15.1.3 15.1.4 15.2.0 15.2.1],
|
||||
dast: %w[15.0.0 15.0.1 15.0.2 15.0.4 15.0.5 15.0.6 15.0.7 15.1.0 15.1.1 15.1.2 15.1.3 15.1.4 15.2.0 15.2.1],
|
||||
api_fuzzing: %w[15.0.0 15.0.1 15.0.2 15.0.4 15.0.5 15.0.6 15.0.7 15.1.0 15.1.1 15.1.2 15.1.3 15.1.4 15.2.0 15.2.1],
|
||||
dependency_scanning: %w[15.0.0 15.0.1 15.0.2 15.0.4 15.0.5 15.0.6 15.0.7 15.1.0 15.1.1 15.1.2 15.1.3 15.1.4 15.2.0 15.2.1],
|
||||
sast: %w[15.0.0 15.0.1 15.0.2 15.0.4 15.0.5 15.0.6 15.0.7 15.1.0 15.1.1 15.1.2 15.1.3 15.1.4 15.2.0 15.2.1],
|
||||
secret_detection: %w[15.0.0 15.0.1 15.0.2 15.0.4 15.0.5 15.0.6 15.0.7 15.1.0 15.1.1 15.1.2 15.1.3 15.1.4 15.2.0 15.2.1]
|
||||
}.freeze
|
||||
|
||||
VERSIONS_TO_REMOVE_IN_18_0 = %w[].freeze
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -9,6 +9,12 @@ module Gitlab
|
|||
|
||||
include JwtAuthenticatable
|
||||
|
||||
class UniqueDomainGenerationFailure < StandardError
|
||||
def initialize(msg = "Can't generate unique domain for GitLab Pages")
|
||||
super(msg)
|
||||
end
|
||||
end
|
||||
|
||||
class << self
|
||||
def verify_api_request(request_headers)
|
||||
decode_jwt(request_headers[INTERNAL_API_REQUEST_HEADER], issuer: 'gitlab-pages')
|
||||
|
|
@ -35,9 +41,7 @@ module Gitlab
|
|||
return if project.project_setting.pages_unique_domain_in_database.present?
|
||||
|
||||
project.project_setting.pages_unique_domain_enabled = true
|
||||
project.project_setting.pages_unique_domain = Gitlab::Pages::RandomDomain.generate(
|
||||
project_path: project.path,
|
||||
namespace_path: project.parent.full_path)
|
||||
project.project_setting.pages_unique_domain = generate_unique_domain(project)
|
||||
end
|
||||
|
||||
def multiple_versions_enabled_for?(project)
|
||||
|
|
@ -47,6 +51,17 @@ module Gitlab
|
|||
project.licensed_feature_available?(:pages_multiple_versions) &&
|
||||
project.project_setting.pages_multiple_versions_enabled
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def generate_unique_domain(project)
|
||||
10.times do
|
||||
pages_unique_domain = Gitlab::Pages::RandomDomain.generate(project_path: project.path)
|
||||
return pages_unique_domain unless ProjectSetting.unique_domain_exists?(pages_unique_domain)
|
||||
end
|
||||
|
||||
raise UniqueDomainGenerationFailure
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,41 +3,27 @@
|
|||
module Gitlab
|
||||
module Pages
|
||||
class RandomDomain
|
||||
PROJECT_PATH_LIMIT = 48
|
||||
SUBDOMAIN_LABEL_LIMIT = 63
|
||||
PROJECT_PATH_LIMIT = 56
|
||||
|
||||
def self.generate(project_path:, namespace_path:)
|
||||
new(project_path: project_path, namespace_path: namespace_path).generate
|
||||
def self.generate(project_path:)
|
||||
new(project_path: project_path).generate
|
||||
end
|
||||
|
||||
def initialize(project_path:, namespace_path:)
|
||||
def initialize(project_path:)
|
||||
@project_path = project_path
|
||||
@namespace_path = namespace_path
|
||||
end
|
||||
|
||||
# Subdomains have a limit of 63 bytes (https://www.freesoft.org/CIE/RFC/1035/9.htm)
|
||||
# For this reason we're limiting each part of the unique subdomain
|
||||
#
|
||||
# The domain is made up of 3 parts, like: projectpath-namespacepath-randomstring
|
||||
# - project path: between 1 and 48 chars
|
||||
# - namespace path: when the project path has less than 48 chars,
|
||||
# the namespace full path will be used to fill the value up to 48 chars
|
||||
# - random hexadecimal: to ensure a random value, the domain is then filled
|
||||
# with a random hexadecimal value to complete 63 chars
|
||||
# The domain is made up of 2 parts, like: projectpath-randomstring
|
||||
# - project path: between 1 and 56 chars
|
||||
# - random hexadecimal: to ensure a random value of length 6
|
||||
def generate
|
||||
domain = project_path.byteslice(0, PROJECT_PATH_LIMIT)
|
||||
|
||||
# if the project_path has less than PROJECT_PATH_LIMIT chars,
|
||||
# fill the domain with the parent full_path up to 48 chars like:
|
||||
# projectpath-namespacepath
|
||||
if domain.length < PROJECT_PATH_LIMIT
|
||||
namespace_size = PROJECT_PATH_LIMIT - domain.length - 1
|
||||
domain.concat('-', namespace_path.byteslice(0, namespace_size))
|
||||
end
|
||||
|
||||
# Complete the domain with random hexadecimal values util it is 63 chars long
|
||||
# PS.: SecureRandom.hex return an string twice the size passed as argument.
|
||||
domain.concat('-', SecureRandom.hex(SUBDOMAIN_LABEL_LIMIT - domain.length - 1))
|
||||
domain.concat('-', SecureRandom.hex(3))
|
||||
|
||||
# Slugify ensures the format and size (63 chars) of the given string
|
||||
Gitlab::Utils.slugify(domain)
|
||||
|
|
@ -45,7 +31,7 @@ module Gitlab
|
|||
|
||||
private
|
||||
|
||||
attr_reader :project_path, :namespace_path
|
||||
attr_reader :project_path
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -33730,6 +33730,9 @@ msgstr ""
|
|||
msgid "MergeRequest|No files found"
|
||||
msgstr ""
|
||||
|
||||
msgid "MergeRequest|Remove reviewer"
|
||||
msgstr ""
|
||||
|
||||
msgid "MergeRequest|Reviewed by @%{username} but not yet approved"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -56711,7 +56714,10 @@ msgstr ""
|
|||
msgid "Tracing|Tracing"
|
||||
msgstr ""
|
||||
|
||||
msgid "Tracing|View Logs"
|
||||
msgid "Tracing|View logs"
|
||||
msgstr ""
|
||||
|
||||
msgid "Tracing|View metrics"
|
||||
msgstr ""
|
||||
|
||||
msgid "Tracing|You must select a Service and Operation first."
|
||||
|
|
@ -57334,6 +57340,9 @@ msgstr ""
|
|||
msgid "Unable to parse the vulnerability report's options."
|
||||
msgstr ""
|
||||
|
||||
msgid "Unable to remove a reviewer at the moment, try again later"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unable to save iteration. Please try again"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
gem 'gitlab-qa', '~> 14', '>= 14.13.0', require: 'gitlab/qa'
|
||||
gem 'gitlab_quality-test_tooling', '~> 1.34.0', require: false
|
||||
gem 'gitlab_quality-test_tooling', '~> 1.35.0', require: false
|
||||
gem 'gitlab-utils', path: '../gems/gitlab-utils'
|
||||
gem 'activesupport', '~> 7.0.8.4' # This should stay in sync with the root's Gemfile
|
||||
gem 'allure-rspec', '~> 2.25.0'
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ GEM
|
|||
rainbow (>= 3, < 4)
|
||||
table_print (= 1.5.7)
|
||||
zeitwerk (>= 2, < 3)
|
||||
gitlab_quality-test_tooling (1.34.0)
|
||||
gitlab_quality-test_tooling (1.35.0)
|
||||
activesupport (>= 7.0, < 7.2)
|
||||
amatch (~> 0.4.1)
|
||||
gitlab (~> 4.19)
|
||||
|
|
@ -377,7 +377,7 @@ DEPENDENCIES
|
|||
gitlab-cng!
|
||||
gitlab-qa (~> 14, >= 14.13.0)
|
||||
gitlab-utils!
|
||||
gitlab_quality-test_tooling (~> 1.34.0)
|
||||
gitlab_quality-test_tooling (~> 1.35.0)
|
||||
googleauth (~> 1.9.0)
|
||||
influxdb-client (~> 3.1)
|
||||
junit_merge (~> 0.1.2)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
FactoryBot.define do
|
||||
factory :generic_package, class: 'Packages::Generic::Package', parent: :package do
|
||||
sequence(:name) { |n| "generic-package-#{n}" }
|
||||
version { '1.0.0' }
|
||||
package_type { :generic }
|
||||
|
||||
trait(:with_zip_file) do
|
||||
package_files do
|
||||
[association(:package_file, :generic_zip, package: instance)]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -139,7 +139,9 @@ FactoryBot.define do
|
|||
end
|
||||
end
|
||||
|
||||
factory :generic_package do
|
||||
# TODO: Remove with the rollout of the FF generic_extract_generic_package_model
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/issues/479933
|
||||
factory :generic_package_legacy do
|
||||
sequence(:name) { |n| "generic-package-#{n}" }
|
||||
version { '1.0.0' }
|
||||
package_type { :generic }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe ::Packages::Generic::PackageFinder do
|
||||
RSpec.describe ::Packages::Generic::PackageFinder, feature_category: :package_registry do
|
||||
let_it_be(:project) { create(:project) }
|
||||
let_it_be(:package) { create(:generic_package, project: project) }
|
||||
|
||||
|
|
@ -34,5 +34,27 @@ RSpec.describe ::Packages::Generic::PackageFinder do
|
|||
expect { finder.execute!(package.name, '3.1.4') }
|
||||
.to raise_error(ActiveRecord::RecordNotFound)
|
||||
end
|
||||
|
||||
context 'when generic_extract_generic_package_model is disabled' do
|
||||
let_it_be(:package) { create(:generic_package_legacy, project: project, name: FFaker::Lorem.word) }
|
||||
|
||||
before do
|
||||
stub_feature_flags(generic_extract_generic_package_model: false)
|
||||
end
|
||||
|
||||
it 'finds package by name and version' do
|
||||
found_package = finder.execute!(package.name, package.version)
|
||||
|
||||
expect(found_package).to eq(package)
|
||||
end
|
||||
|
||||
it 'ignores packages with same name but different version' do
|
||||
create(:generic_package_legacy, project: project, name: package.name, version: '3.1.4')
|
||||
|
||||
found_package = finder.execute!(package.name, package.version)
|
||||
|
||||
expect(found_package).to eq(package)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -65,7 +65,6 @@ describe('Create work item component', () => {
|
|||
|
||||
const createComponent = ({
|
||||
props = {},
|
||||
isGroup = false,
|
||||
mutationHandler = createWorkItemSuccessHandler,
|
||||
singleWorkItemType = false,
|
||||
workItemTypeName = WORK_ITEM_TYPE_ENUM_EPIC,
|
||||
|
|
@ -97,7 +96,6 @@ describe('Create work item component', () => {
|
|||
},
|
||||
provide: {
|
||||
fullPath: 'full-path',
|
||||
isGroup,
|
||||
hasIssuableHealthStatusFeature: false,
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -80,14 +80,12 @@ describe('WorkItemTokenInput', () => {
|
|||
[groupWorkItemsQuery, groupSearchedWorkItemResolver],
|
||||
[workItemsByReferencesQuery, workItemReferencesQueryResolver],
|
||||
]),
|
||||
provide: {
|
||||
isGroup,
|
||||
},
|
||||
propsData: {
|
||||
value: workItemsToAdd,
|
||||
childrenType,
|
||||
childrenIds: [],
|
||||
fullPath: 'test-project-path',
|
||||
isGroup,
|
||||
parentWorkItemId: 'gid://gitlab/WorkItem/1',
|
||||
parentConfidential,
|
||||
areWorkItemsToAddValid,
|
||||
|
|
|
|||
|
|
@ -78,9 +78,6 @@ describe('WorkItemAssignees component', () => {
|
|||
]);
|
||||
|
||||
wrapper = mountFn(WorkItemAssignees, {
|
||||
provide: {
|
||||
isGroup: false,
|
||||
},
|
||||
propsData: {
|
||||
assignees,
|
||||
fullPath: 'test-project-path',
|
||||
|
|
|
|||
|
|
@ -70,11 +70,6 @@ describe('WorkItemAttributesWrapper component', () => {
|
|||
groupPath,
|
||||
},
|
||||
provide: {
|
||||
hasIssueWeightsFeature: true,
|
||||
hasIterationsFeature: true,
|
||||
hasOkrsFeature: true,
|
||||
hasIssuableHealthStatusFeature: true,
|
||||
projectNamespace: 'namespace',
|
||||
hasSubepicsFeature: true,
|
||||
glFeatures: {
|
||||
workItemsBeta,
|
||||
|
|
|
|||
|
|
@ -99,7 +99,6 @@ describe('WorkItemDetail component', () => {
|
|||
const findDetailWrapper = () => wrapper.findByTestId('detail-wrapper');
|
||||
|
||||
const createComponent = ({
|
||||
isGroup = false,
|
||||
isModal = false,
|
||||
isDrawer = false,
|
||||
updateInProgress = false,
|
||||
|
|
@ -142,15 +141,9 @@ describe('WorkItemDetail component', () => {
|
|||
workItemsBeta,
|
||||
namespaceLevelWorkItems,
|
||||
},
|
||||
hasIssueWeightsFeature: true,
|
||||
hasIterationsFeature: true,
|
||||
hasOkrsFeature: true,
|
||||
hasSubepicsFeature,
|
||||
hasIssuableHealthStatusFeature: true,
|
||||
projectNamespace: 'namespace',
|
||||
fullPath: 'group/project',
|
||||
groupPath: 'group',
|
||||
isGroup,
|
||||
reportAbusePath: '/report/abuse/path',
|
||||
},
|
||||
stubs: {
|
||||
|
|
|
|||
|
|
@ -82,7 +82,6 @@ describe('WorkItemLabels component', () => {
|
|||
]),
|
||||
provide: {
|
||||
canAdminLabel: true,
|
||||
isGroup,
|
||||
issuesListPath: 'test-project-path/issues',
|
||||
labelsManagePath: 'test-project-path/labels',
|
||||
},
|
||||
|
|
@ -91,6 +90,7 @@ describe('WorkItemLabels component', () => {
|
|||
workItemIid,
|
||||
canUpdate,
|
||||
fullPath: 'test-project-path',
|
||||
isGroup,
|
||||
workItemType: 'Task',
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ describe('WorkItemLinksForm', () => {
|
|||
]),
|
||||
propsData: {
|
||||
fullPath: 'group-a',
|
||||
isGroup,
|
||||
issuableGid: 'gid://gitlab/WorkItem/1',
|
||||
parentConfidential,
|
||||
parentIteration,
|
||||
|
|
@ -105,7 +106,6 @@ describe('WorkItemLinksForm', () => {
|
|||
},
|
||||
provide: {
|
||||
hasIterationsFeature,
|
||||
isGroup,
|
||||
},
|
||||
stubs: {
|
||||
GlFormGroup: stubComponent(GlFormGroup, {
|
||||
|
|
|
|||
|
|
@ -62,7 +62,6 @@ describe('WorkItemParent component', () => {
|
|||
parent = null,
|
||||
searchQueryHandler = availableWorkItemsSuccessHandler,
|
||||
mutationHandler = successUpdateWorkItemMutationHandler,
|
||||
isGroup = false,
|
||||
hasParent = true,
|
||||
} = {}) => {
|
||||
wrapper = mountExtended(WorkItemParent, {
|
||||
|
|
@ -74,7 +73,6 @@ describe('WorkItemParent component', () => {
|
|||
]),
|
||||
provide: {
|
||||
fullPath: mockFullPath,
|
||||
isGroup,
|
||||
},
|
||||
propsData: {
|
||||
canUpdate,
|
||||
|
|
|
|||
|
|
@ -34,9 +34,6 @@ describe('WorkItemAddRelationshipForm', () => {
|
|||
|
||||
wrapper = shallowMountExtended(WorkItemAddRelationshipForm, {
|
||||
apolloProvider: mockApolloProvider,
|
||||
provide: {
|
||||
isGroup: false,
|
||||
},
|
||||
propsData: {
|
||||
workItemId,
|
||||
workItemIid,
|
||||
|
|
|
|||
|
|
@ -421,6 +421,18 @@ RSpec.describe Gitlab::Ci::Config::Interpolation::Inputs, feature_category: :pip
|
|||
end
|
||||
end
|
||||
|
||||
context 'when given a value that is not a string' do
|
||||
let(:specs) { { test_input: { regex: '^input_value$' } } }
|
||||
let(:args) { { test_input: 999 } }
|
||||
|
||||
it 'is invalid' do
|
||||
expect(inputs).not_to be_valid
|
||||
expect(inputs.errors).to contain_exactly(
|
||||
'`test_input` input: provided value is not a string'
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the pattern is unsafe' do
|
||||
let(:specs) { { test_input: { regex: 'a++' } } }
|
||||
let(:args) { { test_input: 'aaaaaaaaaaaaaaaaaaaaa' } }
|
||||
|
|
|
|||
|
|
@ -3,10 +3,8 @@
|
|||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::Pages::RandomDomain, feature_category: :pages do
|
||||
let(:namespace_path) { 'namespace' }
|
||||
|
||||
subject(:generator) do
|
||||
described_class.new(project_path: project_path, namespace_path: namespace_path)
|
||||
described_class.new(project_path: project_path)
|
||||
end
|
||||
|
||||
RSpec.shared_examples 'random domain' do |domain|
|
||||
|
|
@ -14,31 +12,30 @@ RSpec.describe Gitlab::Pages::RandomDomain, feature_category: :pages do
|
|||
expect(SecureRandom)
|
||||
.to receive(:hex)
|
||||
.and_wrap_original do |_, size, _|
|
||||
('h' * size)
|
||||
('h' * size * 2)
|
||||
end
|
||||
|
||||
generated = generator.generate
|
||||
|
||||
expect(generated).to eq(domain)
|
||||
expect(generated.length).to eq(63)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when project path is less than 48 chars' do
|
||||
let(:project_path) { 'p' }
|
||||
|
||||
it_behaves_like 'random domain', 'p-namespace-hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh'
|
||||
it_behaves_like 'random domain', 'p-hhhhhh'
|
||||
end
|
||||
|
||||
context 'when project path is close to 48 chars' do
|
||||
let(:project_path) { 'p' * 45 }
|
||||
let(:project_path) { 'p' * 56 }
|
||||
|
||||
it_behaves_like 'random domain', 'ppppppppppppppppppppppppppppppppppppppppppppp-na-hhhhhhhhhhhhhh'
|
||||
it_behaves_like 'random domain', 'pppppppppppppppppppppppppppppppppppppppppppppppppppppppp-hhhhhh'
|
||||
end
|
||||
|
||||
context 'when project path is larger than 48 chars' do
|
||||
let(:project_path) { 'p' * 49 }
|
||||
let(:project_path) { 'p' * 57 }
|
||||
|
||||
it_behaves_like 'random domain', 'pppppppppppppppppppppppppppppppppppppppppppppppp-hhhhhhhhhhhhhh'
|
||||
it_behaves_like 'random domain', 'pppppppppppppppppppppppppppppppppppppppppppppppppppppppp-hhhhhh'
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -131,6 +131,36 @@ RSpec.describe Gitlab::Pages, feature_category: :pages do
|
|||
expect(project.project_setting.pages_unique_domain).to eq('unique-domain')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when a unique domain is already in use and needs to generate a new one' do
|
||||
it 'generates a different unique domain if the original is already taken' do
|
||||
allow(Gitlab::Pages::RandomDomain).to receive(:generate).and_return('existing-domain', 'new-unique-domain')
|
||||
|
||||
# Simulate the existing domain being in use
|
||||
create(:project_setting, pages_unique_domain: 'existing-domain')
|
||||
|
||||
described_class.add_unique_domain_to(project)
|
||||
|
||||
expect(project.project_setting.pages_unique_domain_enabled).to eq(true)
|
||||
expect(project.project_setting.pages_unique_domain).to eq('new-unique-domain')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when generated 10 unique domains are already in use' do
|
||||
it 'raises an error' do
|
||||
allow(Gitlab::Pages::RandomDomain).to receive(:generate).and_return('existing-domain')
|
||||
|
||||
# Simulate the existing domain being in use
|
||||
create(:project_setting, pages_unique_domain: 'existing-domain')
|
||||
|
||||
expect { described_class.add_unique_domain_to(project) }.to raise_error(
|
||||
described_class::UniqueDomainGenerationFailure,
|
||||
"Can't generate unique domain for GitLab Pages"
|
||||
)
|
||||
|
||||
expect(project.project_setting.pages_unique_domain).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Packages::Generic::Package, type: :model, feature_category: :package_registry do
|
||||
describe 'validations' do
|
||||
describe '#name' do
|
||||
it { is_expected.to allow_value('123').for(:name) }
|
||||
it { is_expected.to allow_value('foo').for(:name) }
|
||||
it { is_expected.to allow_value('foo.bar.baz-2.0-20190901.47283-1').for(:name) }
|
||||
it { is_expected.not_to allow_value('../../foo').for(:name) }
|
||||
it { is_expected.not_to allow_value('..\..\foo').for(:name) }
|
||||
it { is_expected.not_to allow_value('%2f%2e%2e%2f%2essh%2fauthorized_keys').for(:name) }
|
||||
it { is_expected.not_to allow_value('$foo/bar').for(:name) }
|
||||
it { is_expected.not_to allow_value('my file name').for(:name) }
|
||||
it { is_expected.not_to allow_value('!!().for(:name)().for(:name)').for(:name) }
|
||||
end
|
||||
|
||||
describe '#version' do
|
||||
it { is_expected.to validate_presence_of(:version) }
|
||||
it { is_expected.to allow_value('1.2.3').for(:version) }
|
||||
it { is_expected.to allow_value('1.3.350').for(:version) }
|
||||
it { is_expected.to allow_value('1.3.350-20201230123456').for(:version) }
|
||||
it { is_expected.to allow_value('1.2.3-rc1').for(:version) }
|
||||
it { is_expected.to allow_value('1.2.3g').for(:version) }
|
||||
it { is_expected.to allow_value('1.2').for(:version) }
|
||||
it { is_expected.to allow_value('1.2.bananas').for(:version) }
|
||||
it { is_expected.to allow_value('v1.2.4-build').for(:version) }
|
||||
it { is_expected.to allow_value('d50d836eb3de6177ce6c7a5482f27f9c2c84b672').for(:version) }
|
||||
it { is_expected.to allow_value('this_is_a_string_only').for(:version) }
|
||||
it { is_expected.not_to allow_value('..1.2.3').for(:version) }
|
||||
it { is_expected.not_to allow_value(' 1.2.3').for(:version) }
|
||||
it { is_expected.not_to allow_value("1.2.3 \r\t").for(:version) }
|
||||
it { is_expected.not_to allow_value("\r\t 1.2.3").for(:version) }
|
||||
it { is_expected.not_to allow_value('1.2.3-4/../../').for(:version) }
|
||||
it { is_expected.not_to allow_value('1.2.3-4%2e%2e%').for(:version) }
|
||||
it { is_expected.not_to allow_value('../../../../../1.2.3').for(:version) }
|
||||
it { is_expected.not_to allow_value('%2e%2e%2f1.2.3').for(:version) }
|
||||
it { is_expected.not_to allow_value('').for(:version) }
|
||||
it { is_expected.not_to allow_value(nil).for(:version) }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#publish_creation_event' do
|
||||
let_it_be(:project) { create(:project) }
|
||||
|
||||
let(:version) { '-' }
|
||||
|
||||
subject(:create_package) { described_class.create!(project: project, name: 'incoming', version: version) }
|
||||
|
||||
it 'publishes an event' do
|
||||
expect { create_package }
|
||||
.to publish_event(::Packages::PackageCreatedEvent)
|
||||
.with({
|
||||
project_id: project.id,
|
||||
id: kind_of(Numeric),
|
||||
name: 'incoming',
|
||||
version: '-',
|
||||
package_type: 'generic'
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -111,6 +111,8 @@ RSpec.describe Packages::Package, type: :model, feature_category: :package_regis
|
|||
it { is_expected.to allow_value("my.app-11.07.2018").for(:name) }
|
||||
it { is_expected.not_to allow_value("my(dom$$$ain)com.my-app").for(:name) }
|
||||
|
||||
# TODO: Remove with the rollout of the FF generic_extract_generic_package_model
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/issues/479933
|
||||
context 'generic package' do
|
||||
subject { build_stubbed(:generic_package) }
|
||||
|
||||
|
|
@ -262,6 +264,8 @@ RSpec.describe Packages::Package, type: :model, feature_category: :package_regis
|
|||
it { is_expected.not_to allow_value('%2e%2e%2f1.2.3').for(:version) }
|
||||
end
|
||||
|
||||
# TODO: Remove with the rollout of the FF generic_extract_generic_package_model
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/issues/479933
|
||||
context 'generic package' do
|
||||
subject { build_stubbed(:generic_package) }
|
||||
|
||||
|
|
@ -1173,34 +1177,65 @@ RSpec.describe Packages::Package, type: :model, feature_category: :package_regis
|
|||
it { is_expected.to eq(normalized_version) }
|
||||
end
|
||||
|
||||
describe "#publish_creation_event" do
|
||||
describe '#publish_creation_event' do
|
||||
let_it_be(:project) { create(:project) }
|
||||
|
||||
let(:version) { '-' }
|
||||
let(:package_type) { :generic }
|
||||
let(:package) { build_stubbed(:generic_package) }
|
||||
|
||||
subject { described_class.create!(project: project, name: 'incoming', version: version, package_type: package_type) }
|
||||
|
||||
context 'when package is generic' do
|
||||
it 'publishes an event' do
|
||||
expect { subject }
|
||||
.to publish_event(::Packages::PackageCreatedEvent)
|
||||
.with({
|
||||
project_id: project.id,
|
||||
id: kind_of(Numeric),
|
||||
name: "incoming",
|
||||
version: "-",
|
||||
package_type: 'generic'
|
||||
})
|
||||
end
|
||||
it 'publishes an event' do
|
||||
expect { package.publish_creation_event }
|
||||
.to publish_event(::Packages::PackageCreatedEvent)
|
||||
.with({
|
||||
project_id: package.project_id,
|
||||
id: package.id,
|
||||
name: package.name,
|
||||
version: package.version,
|
||||
package_type: package.package_type
|
||||
})
|
||||
end
|
||||
|
||||
context 'when package is not generic' do
|
||||
let(:package_type) { :debian }
|
||||
let(:version) { 1 }
|
||||
# TODO: Remove with the rollout of the FF generic_extract_generic_package_model
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/issues/479933
|
||||
context 'with after_create_commit callback' do
|
||||
let(:name) { FFaker::Lorem.word }
|
||||
let(:version) { '1.0.0' }
|
||||
|
||||
it 'does not create event' do
|
||||
expect { subject }.not_to publish_event(::Packages::PackageCreatedEvent)
|
||||
subject(:create_package) do
|
||||
described_class.create!(project: project, name: name, version: version, package_type: package_type)
|
||||
end
|
||||
|
||||
context 'when package is generic' do
|
||||
let(:package_type) { 'generic' }
|
||||
|
||||
it 'does not create event' do
|
||||
expect { create_package }.not_to publish_event(::Packages::PackageCreatedEvent)
|
||||
end
|
||||
|
||||
context 'when generic_extract_generic_package_model is disabled' do
|
||||
before do
|
||||
stub_feature_flags(generic_extract_generic_package_model: false)
|
||||
end
|
||||
|
||||
it 'publishes an event' do
|
||||
expect { create_package }
|
||||
.to publish_event(::Packages::PackageCreatedEvent)
|
||||
.with({
|
||||
project_id: project.id,
|
||||
id: kind_of(Numeric),
|
||||
name: name,
|
||||
version: version,
|
||||
package_type: package_type
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when package is not generic' do
|
||||
let(:package_type) { 'debian' }
|
||||
|
||||
it 'does not create event' do
|
||||
expect { create_package }.not_to publish_event(::Packages::PackageCreatedEvent)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1237,5 +1272,19 @@ RSpec.describe Packages::Package, type: :model, feature_category: :package_regis
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when generic_extract_generic_package_model is disabled' do
|
||||
before do
|
||||
stub_feature_flags(generic_extract_generic_package_model: false)
|
||||
end
|
||||
|
||||
context 'for package format generic' do
|
||||
let(:format) { :generic }
|
||||
|
||||
it 'maps to Packages::Package' do
|
||||
is_expected.to eq(described_class)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue