Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2024-10-23 18:15:56 +00:00
parent 93bb7ebeab
commit cae885f7a8
88 changed files with 906 additions and 811 deletions

View File

@ -1 +1 @@
64d528040625ca4350ce1d0f1df4f037f0cc5d37
b1dfcadfaf2771f7a966b9eae97478c5fc8d7d9d

View File

@ -1 +1 @@
e2d561ff32972e193d836ea34c34a2f45a2b312c
a92cf38ec9c34a3ccb4d8c07acadc3935fd250ef

View File

@ -493,7 +493,7 @@ end
group :development, :test do
gem 'deprecation_toolkit', '~> 1.5.1', require: false # rubocop:todo Gemfile/MissingFeatureCategory
gem 'bullet', '~> 7.1.2' # rubocop:todo Gemfile/MissingFeatureCategory
gem 'parser', '= 3.3.3.0', feature_category: :shared
gem 'parser', '= 3.3.5.0', feature_category: :shared
gem 'pry-byebug' # rubocop:todo Gemfile/MissingFeatureCategory
gem 'pry-rails', '~> 0.3.9' # rubocop:todo Gemfile/MissingFeatureCategory
gem 'pry-shell', '~> 0.6.4' # rubocop:todo Gemfile/MissingFeatureCategory

View File

@ -289,7 +289,6 @@
{"name":"grape-swagger","version":"2.1.1","platform":"ruby","checksum":"f54d89ba1dae6cac50c5566ceab50ef22bdad9bed2bbaefd4b37b764d7503c1d"},
{"name":"grape-swagger-entity","version":"0.5.5","platform":"ruby","checksum":"a2a0eb28964b1a56775a3571358a9f0a300b703dbaee1ee535adb2a7bed7ece6"},
{"name":"grape_logging","version":"1.8.4","platform":"ruby","checksum":"efcc3e322dbd5d620a68f078733b7db043cf12680144cd03c982f14115c792d1"},
{"name":"graphiql-rails","version":"1.10.0","platform":"ruby","checksum":"b557f989a737c8b9e985142609bec52fb1e9393a701eb50e02a7c14422891040"},
{"name":"graphlient","version":"0.8.0","platform":"ruby","checksum":"98c408da1d083454e9f5e274f3b0b6261e2a0c2b5f2ed7b3ef9441d46f8e7cb1"},
{"name":"graphlyte","version":"1.0.0","platform":"ruby","checksum":"b5af4ab67dde6e961f00ea1c18f159f73b52ed11395bb4ece297fe628fa1804d"},
{"name":"graphql","version":"2.3.18","platform":"ruby","checksum":"e62cde33a0eeab3a6e31eaf5d9ca0a711d3aea477ab050825404e869fb25a5fc"},
@ -310,7 +309,7 @@
{"name":"guard-compat","version":"1.2.1","platform":"ruby","checksum":"3ad21ab0070107f92edfd82610b5cdc2fb8e368851e72362ada9703443d646fe"},
{"name":"guard-rspec","version":"4.7.3","platform":"ruby","checksum":"a47ba03cbd1e3c71e6ae8645cea97e203098a248aede507461a43e906e2f75ca"},
{"name":"haml","version":"5.2.2","platform":"ruby","checksum":"6e759246556145642ef832d670fc06f9bd8539159a0e600847a00291dd7aae0c"},
{"name":"haml_lint","version":"0.58.0","platform":"ruby","checksum":"2f796864779a213d6d037c923a8063327e0bd25971f1eb81452699d96523c2d5"},
{"name":"haml_lint","version":"0.59.0","platform":"ruby","checksum":"22e82b548f2fe33f231261b2c40fe5dccfd2a6f2c774d092592a3ab0ec2f84b1"},
{"name":"hamlit","version":"2.15.0","platform":"java","checksum":"fda165464e59337ab7cda6304a66bfdb607bb7155f25566da19c9ee7b98e03d1"},
{"name":"hamlit","version":"2.15.0","platform":"ruby","checksum":"d2e8505362338945fa309c68b2b8be07ebdc181200ec6021223567bf66dac38e"},
{"name":"hana","version":"1.3.7","platform":"ruby","checksum":"5425db42d651fea08859811c29d20446f16af196308162894db208cac5ce9b0d"},
@ -500,7 +499,7 @@
{"name":"pact-support","version":"1.20.0","platform":"ruby","checksum":"41c343a3124fb379684b9ad9f1a0766c5fa18d3b78d433a52e5552d8b9475871"},
{"name":"paper_trail","version":"15.1.0","platform":"ruby","checksum":"0dbccd97e9d26c54aaea256d2566eaa040a3535601f49a62d79187e77d9ba9f9"},
{"name":"parallel","version":"1.24.0","platform":"ruby","checksum":"5bf38efb9b37865f8e93d7a762727f8c5fc5deb19949f4040c76481d5eee9397"},
{"name":"parser","version":"3.3.3.0","platform":"ruby","checksum":"a2e23c90918d9b7e866b18dca2b6835f227769dd2fa8e59c5841f3389cf53eeb"},
{"name":"parser","version":"3.3.5.0","platform":"ruby","checksum":"f30ebb71b7830c2e7cdc4b2b0e0ec2234900e3fca3fe2fba47f78be759181ab3"},
{"name":"parslet","version":"1.8.2","platform":"ruby","checksum":"08d1ab3721cd3f175bfbee8788b2ddff71f92038f2d69bd65454c22bb9fbd98a"},
{"name":"pastel","version":"0.8.0","platform":"ruby","checksum":"481da9fb7d2f6e6b1a08faf11fa10363172dc40fd47848f096ae21209f805a75"},
{"name":"peek","version":"1.1.0","platform":"ruby","checksum":"d6501ead8cde46d8d8ed0d59eb6f0ba713d0a41c11a2c4a81447b2dce37b3ecc"},

View File

@ -959,7 +959,7 @@ GEM
haml (5.2.2)
temple (>= 0.8.0)
tilt
haml_lint (0.58.0)
haml_lint (0.59.0)
haml (>= 5.0)
parallel (~> 1.10)
rainbow
@ -1404,7 +1404,7 @@ GEM
activerecord (>= 6.1)
request_store (~> 1.4)
parallel (1.24.0)
parser (3.3.3.0)
parser (3.3.5.0)
ast (~> 2.4.1)
racc
parslet (1.8.2)
@ -2215,7 +2215,7 @@ DEPENDENCIES
pact (~> 1.64)
paper_trail (~> 15.0)
parallel (~> 1.19)
parser (= 3.3.3.0)
parser (= 3.3.5.0)
parslet (~> 1.8)
peek (~> 1.1)
pg (~> 1.5.6)

View File

@ -310,7 +310,7 @@
{"name":"guard-compat","version":"1.2.1","platform":"ruby","checksum":"3ad21ab0070107f92edfd82610b5cdc2fb8e368851e72362ada9703443d646fe"},
{"name":"guard-rspec","version":"4.7.3","platform":"ruby","checksum":"a47ba03cbd1e3c71e6ae8645cea97e203098a248aede507461a43e906e2f75ca"},
{"name":"haml","version":"5.2.2","platform":"ruby","checksum":"6e759246556145642ef832d670fc06f9bd8539159a0e600847a00291dd7aae0c"},
{"name":"haml_lint","version":"0.58.0","platform":"ruby","checksum":"2f796864779a213d6d037c923a8063327e0bd25971f1eb81452699d96523c2d5"},
{"name":"haml_lint","version":"0.59.0","platform":"ruby","checksum":"22e82b548f2fe33f231261b2c40fe5dccfd2a6f2c774d092592a3ab0ec2f84b1"},
{"name":"hamlit","version":"2.15.0","platform":"java","checksum":"fda165464e59337ab7cda6304a66bfdb607bb7155f25566da19c9ee7b98e03d1"},
{"name":"hamlit","version":"2.15.0","platform":"ruby","checksum":"d2e8505362338945fa309c68b2b8be07ebdc181200ec6021223567bf66dac38e"},
{"name":"hana","version":"1.3.7","platform":"ruby","checksum":"5425db42d651fea08859811c29d20446f16af196308162894db208cac5ce9b0d"},
@ -504,7 +504,7 @@
{"name":"pact-support","version":"1.20.0","platform":"ruby","checksum":"41c343a3124fb379684b9ad9f1a0766c5fa18d3b78d433a52e5552d8b9475871"},
{"name":"paper_trail","version":"15.1.0","platform":"ruby","checksum":"0dbccd97e9d26c54aaea256d2566eaa040a3535601f49a62d79187e77d9ba9f9"},
{"name":"parallel","version":"1.24.0","platform":"ruby","checksum":"5bf38efb9b37865f8e93d7a762727f8c5fc5deb19949f4040c76481d5eee9397"},
{"name":"parser","version":"3.3.3.0","platform":"ruby","checksum":"a2e23c90918d9b7e866b18dca2b6835f227769dd2fa8e59c5841f3389cf53eeb"},
{"name":"parser","version":"3.3.5.0","platform":"ruby","checksum":"f30ebb71b7830c2e7cdc4b2b0e0ec2234900e3fca3fe2fba47f78be759181ab3"},
{"name":"parslet","version":"1.8.2","platform":"ruby","checksum":"08d1ab3721cd3f175bfbee8788b2ddff71f92038f2d69bd65454c22bb9fbd98a"},
{"name":"pastel","version":"0.8.0","platform":"ruby","checksum":"481da9fb7d2f6e6b1a08faf11fa10363172dc40fd47848f096ae21209f805a75"},
{"name":"peek","version":"1.1.0","platform":"ruby","checksum":"d6501ead8cde46d8d8ed0d59eb6f0ba713d0a41c11a2c4a81447b2dce37b3ecc"},

View File

@ -969,7 +969,7 @@ GEM
haml (5.2.2)
temple (>= 0.8.0)
tilt
haml_lint (0.58.0)
haml_lint (0.59.0)
haml (>= 5.0)
parallel (~> 1.10)
rainbow
@ -1419,7 +1419,7 @@ GEM
activerecord (>= 6.1)
request_store (~> 1.4)
parallel (1.24.0)
parser (3.3.3.0)
parser (3.3.5.0)
ast (~> 2.4.1)
racc
parslet (1.8.2)
@ -2242,7 +2242,7 @@ DEPENDENCIES
pact (~> 1.64)
paper_trail (~> 15.0)
parallel (~> 1.19)
parser (= 3.3.3.0)
parser (= 3.3.5.0)
parslet (~> 1.8)
peek (~> 1.1)
pg (~> 1.5.6)

View File

@ -19,14 +19,11 @@ export default {
ToolbarMoreDropdown,
CommentTemplatesModal,
HeaderDivider,
SummarizeCodeChanges: () =>
import('ee_component/merge_requests/components/summarize_code_changes.vue'),
},
inject: {
newCommentTemplatePaths: { default: () => [] },
tiptapEditor: { default: null },
contentEditor: { default: null },
canSummarize: { default: false },
},
props: {
supportsQuickActions: {
@ -210,9 +207,5 @@ export default {
@select="insertSavedReply"
/>
<toolbar-more-dropdown data-testid="more" @execute="trackToolbarControlExecution" />
<div v-if="canSummarize" class="gl-flex">
<header-divider />
<summarize-code-changes />
</div>
</div>
</template>

View File

@ -547,6 +547,10 @@ export default class Notes {
renderGFM(discussionElement);
const $discussion = $(discussionElement).unwrap();
if (noteEntity.on_image) {
discussionElement.classList.add('discussion-notes', 'gl-block');
}
if (!this.isParallelView() || row.hasClass('js-temp-notes-holder') || noteEntity.on_image) {
// insert the note and the reply button after the temp row
row.after($discussion);

View File

@ -13,8 +13,7 @@ export default {
},
canWriteModelRegistry: {
type: Boolean,
required: false,
default: false,
required: true,
},
markdownPreviewPath: {
type: String,

View File

@ -0,0 +1,62 @@
<script>
import ModelVersionEdit from '../components/model_version_edit.vue';
export default {
name: 'EditMlModelVersion',
components: {
ModelVersionEdit,
},
props: {
projectPath: {
type: String,
required: true,
},
canWriteModelRegistry: {
type: Boolean,
required: true,
},
markdownPreviewPath: {
type: String,
required: true,
},
modelVersionPath: {
type: String,
required: true,
},
modelGid: {
type: String,
required: true,
},
modelVersionVersion: {
type: String,
required: true,
},
modelVersionDescription: {
type: String,
required: true,
},
},
computed: {
modelWithModelVersion() {
return {
id: this.modelGid,
version: {
version: this.modelVersionVersion,
description: this.modelVersionDescription,
},
};
},
},
};
</script>
<template>
<model-version-edit
v-if="canWriteModelRegistry"
:model-with-version="modelWithModelVersion"
:project-path="projectPath"
:markdown-preview-path="markdownPreviewPath"
:model-version-path="modelVersionPath"
:disable-attachments="false"
/>
</template>

View File

@ -1,12 +1,14 @@
import ShowMlModel from './show_ml_model.vue';
import ShowMlModelVersion from './show_ml_model_version.vue';
import NewMlModelVersion from './new_ml_model_version.vue';
import EditMlModel from './edit_ml_model.vue';
import EditMlModelVersion from './edit_ml_model_version.vue';
import IndexMlModels from './index_ml_models.vue';
import NewMlModel from './new_ml_model.vue';
import EditMlModel from './edit_ml_model.vue';
import NewMlModelVersion from './new_ml_model_version.vue';
import ShowMlModel from './show_ml_model.vue';
import ShowMlModelVersion from './show_ml_model_version.vue';
export {
EditMlModel,
EditMlModelVersion,
IndexMlModels,
NewMlModel,
NewMlModelVersion,

View File

@ -20,8 +20,7 @@ export default {
},
canWriteModelRegistry: {
type: Boolean,
required: false,
default: false,
required: true,
},
maxAllowedFileSize: {
type: Number,

View File

@ -20,8 +20,7 @@ export default {
},
canWriteModelRegistry: {
type: Boolean,
required: false,
default: false,
required: true,
},
maxAllowedFileSize: {
type: Number,

View File

@ -1,5 +1,5 @@
<script>
import { GlSprintf, GlIcon, GlLink } from '@gitlab/ui';
import { GlButton, GlSprintf, GlIcon, GlLink } from '@gitlab/ui';
import TitleArea from '~/vue_shared/components/registry/title_area.vue';
import * as Sentry from '~/sentry/sentry_browser_wrapper';
import { createAlert, VARIANT_DANGER } from '~/alert';
@ -14,16 +14,15 @@ import timeagoMixin from '~/vue_shared/mixins/timeago';
import ModelVersionDetail from '../components/model_version_detail.vue';
import LoadOrErrorOrShow from '../components/load_or_error_or_show.vue';
import ModelVersionActionsDropdown from '../components/model_version_actions_dropdown.vue';
import ModelVersionEdit from '../components/model_version_edit.vue';
export default {
name: 'ShowMlModelVersionApp',
components: {
GlButton,
LoadOrErrorOrShow,
ModelVersionDetail,
ModelVersionActionsDropdown,
TitleArea,
ModelVersionEdit,
GlIcon,
GlLink,
GlSprintf,
@ -73,6 +72,10 @@ export default {
type: String,
required: true,
},
editModelVersionPath: {
type: String,
required: true,
},
maxAllowedFileSize: {
type: Number,
required: true,
@ -182,6 +185,9 @@ export default {
}
},
},
i18n: {
editModelVersionButtonLabel: s__('MlModelRegistry|Edit model version'),
},
};
</script>
@ -216,10 +222,13 @@ export default {
</title-area>
</div>
<div class="gl-mt-3 gl-flex gl-items-start gl-gap-3">
<model-version-edit
v-if="modelVersion && canWriteModelRegistry"
:model-with-version="modelWithModelVersion"
/>
<gl-button
v-if="canWriteModelRegistry"
data-testid="edit-model-version-button"
variant="confirm"
:href="editModelVersionPath"
>{{ $options.i18n.editModelVersionButtonLabel }}</gl-button
>
<model-version-actions-dropdown @delete-model-version="deleteModelVersion" />
</div>
</div>

View File

@ -1,12 +1,12 @@
<script>
import { GlAlert, GlButton, GlForm, GlFormGroup, GlModal, GlModalDirective } from '@gitlab/ui';
import { GlAlert, GlButton, GlForm, GlFormGroup } from '@gitlab/ui';
import { __, s__ } from '~/locale';
import { visitUrl } from '~/lib/utils/url_utility';
import * as Sentry from '~/sentry/sentry_browser_wrapper';
import MarkdownEditor from '~/vue_shared/components/markdown/markdown_editor.vue';
import { helpPagePath } from '~/helpers/help_page_helper';
import editModelVersionMutation from '../graphql/mutations/edit_model_version.mutation.graphql';
import { emptyArtifactFile, MODEL_VERSION_EDIT_MODAL_ID } from '../constants';
import { emptyArtifactFile } from '../constants';
export default {
name: 'ModelVersionEdit',
@ -14,19 +14,26 @@ export default {
MarkdownEditor,
GlAlert,
GlButton,
GlModal,
GlForm,
GlFormGroup,
},
directives: {
GlModal: GlModalDirective,
},
inject: ['projectPath', 'maxAllowedFileSize', 'markdownPreviewPath'],
props: {
modelWithVersion: {
type: Object,
required: true,
},
projectPath: {
type: String,
required: true,
},
markdownPreviewPath: {
type: String,
required: true,
},
modelVersionPath: {
type: String,
required: true,
},
disableAttachments: {
type: Boolean,
required: false,
@ -45,17 +52,9 @@ export default {
autocompleteDataSources() {
return gl.GfmAutoComplete?.dataSources;
},
actionPrimary() {
return {
text: s__('MlModelRegistry|Save changes'),
attributes: { variant: 'confirm' },
};
},
},
methods: {
async edit($event) {
$event.preventDefault();
async edit() {
this.errorMessage = '';
try {
const { data } = await this.$apollo.mutate({
@ -92,16 +91,12 @@ export default {
id: 'model-version-description',
name: 'model-version-description',
},
modal: {
id: MODEL_VERSION_EDIT_MODAL_ID,
actionSecondary: {
text: __('Cancel'),
attributes: { variant: 'default' },
},
i18n: {
actionPrimaryText: s__('MlModelRegistry|Save changes'),
actionSecondaryText: __('Cancel'),
descriptionPlaceholder: s__('MlModelRegistry|Enter some description'),
descriptionLabel: s__('MlModelRegistry|Description'),
editButtonLabel: s__('MlModelRegistry|Edit model version'),
title: s__('MlModelRegistry|Edit version'),
title: s__('MlModelRegistry|Edit model version'),
optionalText: s__('MlModelRegistry|(Optional)'),
},
};
@ -109,49 +104,41 @@ export default {
<template>
<div>
<gl-button v-gl-modal="$options.modal.id">{{ $options.modal.editButtonLabel }}</gl-button>
<gl-modal
:modal-id="$options.modal.id"
:title="$options.modal.title"
:action-primary="actionPrimary"
:action-secondary="$options.modal.actionSecondary"
size="lg"
@primary="edit"
>
<gl-form>
<gl-form-group
:label="$options.modal.descriptionLabel"
data-testid="description-group-id"
label-for="descriptionId"
optional
:optional-text="$options.modal.optionalText"
class="common-note-form gfm-form js-main-target-form new-note gl-grow"
>
<markdown-editor
ref="markdownEditor"
data-testid="description-id"
:value="modelWithVersion.version.description"
enable-autocomplete
:autocomplete-data-sources="autocompleteDataSources"
enable-content-editor
:form-field-props="$options.descriptionFormFieldProps"
:render-markdown-path="markdownPreviewPath"
:markdown-docs-path="markdownDocPath"
:disable-attachments="disableAttachments"
:placeholder="$options.modal.nameDescriptionPlaceholder"
:restricted-tool-bar-items="markdownEditorRestrictedToolBarItems"
@input="setDescription"
/>
</gl-form-group>
</gl-form>
<gl-alert
v-if="errorMessage"
data-testid="modal-edit-alert"
variant="danger"
@dismiss="hideAlert"
>{{ errorMessage }}
</gl-alert>
</gl-modal>
<h2>{{ $options.i18n.title }}</h2>
<gl-form>
<gl-form-group
:label="$options.i18n.descriptionLabel"
data-testid="description-group-id"
label-for="descriptionId"
optional
:optional-text="$options.i18n.optionalText"
class="common-note-form gfm-form js-main-target-form new-note gl-grow"
>
<markdown-editor
ref="markdownEditor"
data-testid="description-id"
:value="modelWithVersion.version.description"
enable-autocomplete
:autocomplete-data-sources="autocompleteDataSources"
enable-content-editor
:form-field-props="$options.descriptionFormFieldProps"
:render-markdown-path="markdownPreviewPath"
:markdown-docs-path="markdownDocPath"
:disable-attachments="disableAttachments"
:placeholder="$options.i18n.nameDescriptionPlaceholder"
:restricted-tool-bar-items="markdownEditorRestrictedToolBarItems"
@input="setDescription"
/>
</gl-form-group>
</gl-form>
<gl-alert v-if="errorMessage" data-testid="edit-alert" variant="danger" @dismiss="hideAlert"
>{{ errorMessage }}
</gl-alert>
<gl-button data-testid="secondary-button" variant="default" :href="modelVersionPath"
>{{ $options.i18n.actionSecondaryText }}
</gl-button>
<gl-button data-testid="primary-button" variant="confirm" @click="edit"
>{{ $options.i18n.actionPrimaryText }}
</gl-button>
</div>
</template>

View File

@ -24,7 +24,6 @@ export const MODEL_ENTITIES = {
};
export const MLFLOW_USAGE_MODAL_ID = 'model-registry-mlflow-usage-modal';
export const MODEL_VERSION_EDIT_MODAL_ID = 'edit-model-version-modal';
export const emptyArtifactFile = {
file: null,

View File

@ -66,10 +66,7 @@ export default {
return Boolean(this.packageEntity.tags?.nodes && this.packageEntity.tags?.nodes.length);
},
showBadgeProtected() {
return (
Boolean(this.glFeatures.packagesProtectedPackages) &&
Boolean(this.packageEntity?.protectionRuleExists)
);
return Boolean(this.packageEntity?.protectionRuleExists);
},
},
mounted() {

View File

@ -85,7 +85,7 @@ export default {
return Boolean(this.packageEntity.tags?.nodes?.length);
},
showBadgeProtected() {
return this.glFeatures.packagesProtectedPackages && this.packageEntity.protectionRuleExists;
return this.packageEntity.protectionRuleExists;
},
nonDefaultRow() {
return this.packageEntity.status && this.packageEntity.status !== PACKAGE_DEFAULT_STATUS;

View File

@ -43,7 +43,7 @@ export default {
},
computed: {
showProtectedPackagesSettings() {
return this.showPackageRegistrySettings && this.glFeatures.packagesProtectedPackages;
return this.showPackageRegistrySettings;
},
showProtectedContainersSettings() {
return (

View File

@ -4,7 +4,6 @@ import { mountMarkdownEditor } from 'ee_else_ce/vue_shared/components/markdown/m
import { findTargetBranch } from 'ee_else_ce/pages/projects/merge_requests/creations/new/branch_finder';
import { parseBoolean } from '~/lib/utils/common_utils';
import initPipelines from '~/commit/pipelines/pipelines_bundle';
import MergeRequest from '~/merge_request';
import CompareApp from '~/merge_requests/components/compare_app.vue';
@ -119,23 +118,11 @@ if (mrNewCompareNode) {
});
} else {
const mrNewSubmitNode = document.querySelector('.js-merge-request-new-submit');
const { projectId, targetBranch, sourceBranch, canSummarize } =
document.querySelector('.js-markdown-editor').dataset;
// eslint-disable-next-line no-new
new MergeRequest({
action: mrNewSubmitNode.dataset.mrSubmitAction,
});
initPipelines();
// eslint-disable-next-line no-new
new IssuableTemplateSelectors({
warnTemplateOverride: true,
editor: mountMarkdownEditor({
provide: {
projectId,
targetBranch,
sourceBranch,
canSummarize: parseBoolean(canSummarize ?? false),
},
}),
});
new IssuableTemplateSelectors({ warnTemplateOverride: true, editor: mountMarkdownEditor() });
}

View File

@ -0,0 +1,8 @@
import Vue from 'vue';
import VueRouter from 'vue-router';
import { initSimpleApp } from '~/helpers/init_simple_app_helper';
import { EditMlModelVersion } from '~/ml/model_registry/apps';
Vue.use(VueRouter);
initSimpleApp('#js-mount-edit-ml-model-version', EditMlModelVersion, { withApolloProvider: true });

View File

@ -32,8 +32,6 @@ export default {
CommentTemplatesModal,
AiActionsDropdown: () => import('ee_component/ai/components/ai_actions_dropdown.vue'),
HeaderDivider,
SummarizeCodeChanges: () =>
import('ee_component/merge_requests/components/summarize_code_changes.vue'),
},
directives: {
GlTooltip: GlTooltipDirective,
@ -45,7 +43,6 @@ export default {
},
editorAiActions: { default: () => [] },
mrGeneratedContent: { default: null },
canSummarize: { default: false },
},
props: {
previewMarkdown: {
@ -530,10 +527,6 @@ export default {
:new-comment-template-paths="newCommentTemplatePaths"
@select="insertSavedReply"
/>
<template v-if="canSummarize">
<header-divider />
<summarize-code-changes />
</template>
</div>
<div v-if="!previewMarkdown" class="full-screen gl-flex gl-grow gl-justify-end">
<toolbar-button

View File

@ -703,27 +703,27 @@ table.code {
display: block;
width: 100%;
height: 10px;
@apply gl-bg-default;
@apply gl-bg-subtle;
background-image: linear-gradient(45deg,
transparent,
transparent 73%,
$diff-jagged-border-gradient-color 75%,
$white 80%),
$diff-jagged-bg-color 80%),
linear-gradient(225deg,
transparent,
transparent 73%,
$diff-jagged-border-gradient-color 75%,
$white 80%),
$diff-jagged-bg-color 80%),
linear-gradient(135deg,
transparent,
transparent 73%,
$diff-jagged-border-gradient-color 75%,
$white 80%),
$diff-jagged-bg-color 80%),
linear-gradient(-45deg,
transparent,
transparent 73%,
$diff-jagged-border-gradient-color 75%,
$white 80%);
$diff-jagged-bg-color 80%);
background-position: 5px 5px, 0 5px, 0 5px, 5px 5px;
background-size: 10px 10px;
background-repeat: repeat;

View File

@ -215,7 +215,8 @@ $dark-diff-match-color: rgba($white, 0.1);
$diff-image-info-color: #808080;
$diff-view-modes-color: #808080;
$diff-view-modes-border: #c1c1c1;
$diff-jagged-border-gradient-color: $gray-100;
$diff-jagged-border-gradient-color: $gray-200;
$diff-jagged-bg-color: var(--gl-background-color-subtle);
/*
* Fonts

View File

@ -354,7 +354,8 @@
.code-commit .notes-content,
.diff-viewer > .image ~ .note-container {
@apply gl-bg-default;
@apply gl-bg-subtle;
@apply gl-rounded-b-base;
li.note-comment {
padding: $gl-padding-8 $gl-padding-8 $gl-padding-8 $gl-padding;
@ -365,6 +366,7 @@
.note-body {
padding: $gl-padding-4 0 $gl-padding-8;
@apply -gl-mt-4;
margin-left: $note-spacing-left;
}
}

View File

@ -7,8 +7,6 @@ module Groups
feature_category :package_registry
urgency :low
before_action :set_feature_flag_packages_protected_packages, only: [:show, :index]
def index; end
# The show action renders index to allow frontend routing to work on page refresh
@ -21,9 +19,5 @@ module Groups
def verify_packages_enabled!
render_404 unless group.packages_feature_enabled?
end
def set_feature_flag_packages_protected_packages
push_frontend_feature_flag(:packages_protected_packages, group)
end
end
end

View File

@ -3,16 +3,14 @@
module Projects
module Ml
class ModelVersionsController < ::Projects::ApplicationController
before_action :authorize_read_model_registry!
feature_category :mlops
before_action :authorize_read_model_registry!
before_action :authorize_write_model_registry!, only: [:new, :edit]
before_action :set_model_version, only: [:show, :edit]
def show
@model_version = ::Ml::ModelVersion.by_project_id_and_id(@project, params[:model_version_id])
def show; end
return render_404 unless @model_version
@model = @model_version.model
end
def edit; end
def new
@model = ::Ml::Model.by_project_id_and_id(@project, params[:model_model_id])
@ -25,6 +23,18 @@ module Projects
def authorize_read_model_registry!
render_404 unless can?(current_user, :read_model_registry, @project)
end
def authorize_write_model_registry!
render_404 unless can?(current_user, :write_model_registry, @project)
end
def set_model_version
@model_version = ::Ml::ModelVersion.by_project_id_and_id(@project, params[:model_version_id])
return render_404 unless @model_version
@model = @model_version.model
end
end
end
end

View File

@ -8,20 +8,12 @@ module Projects
feature_category :package_registry
urgency :low
before_action :set_feature_flag_packages_protected_packages, only: [:index, :show]
def index; end
# The show action renders index to allow frontend routing to work on page refresh
def show
render :index
end
private
def set_feature_flag_packages_protected_packages
push_frontend_feature_flag(:packages_protected_packages, project)
end
end
end
end

View File

@ -7,7 +7,6 @@ module Projects
before_action :authorize_admin_project!
before_action :packages_and_registries_settings_enabled!
before_action :set_feature_flag_packages_protected_packages, only: :show
before_action :set_feature_flag_packages_protected_packages_pypi, only: :show
before_action :set_feature_flag_container_registry_protected_containers, only: :show
@ -33,10 +32,6 @@ module Projects
can?(current_user, :admin_container_image, project)
end
def set_feature_flag_packages_protected_packages
push_frontend_feature_flag(:packages_protected_packages, project)
end
def set_feature_flag_packages_protected_packages_pypi
push_frontend_feature_flag(:packages_protected_packages_pypi, project)
end

View File

@ -6,8 +6,7 @@ module Mutations
module Rule
class Create < ::Mutations::BaseMutation
graphql_name 'CreatePackagesProtectionRule'
description 'Creates a protection rule to restrict access to project packages. ' \
'Available only when feature flag `packages_protected_packages` is enabled.'
description 'Creates a protection rule to restrict access to project packages.'
include FindsProject
@ -44,10 +43,6 @@ module Mutations
def resolve(project_path:, **kwargs)
project = authorized_find!(project_path)
if Feature.disabled?(:packages_protected_packages, project)
raise_resource_not_available_error!("'packages_protected_packages' feature flag is disabled")
end
response = ::Packages::Protection::CreateRuleService.new(project: project, current_user: current_user,
params: kwargs).execute

View File

@ -6,8 +6,7 @@ module Mutations
module Rule
class Delete < ::Mutations::BaseMutation
graphql_name 'DeletePackagesProtectionRule'
description 'Deletes a protection rule for packages. ' \
'Available only when feature flag `packages_protected_packages` is enabled.'
description 'Deletes a protection rule for packages.'
authorize :admin_package
@ -25,10 +24,6 @@ module Mutations
def resolve(id:, **_kwargs)
package_protection_rule = authorized_find!(id: id)
if Feature.disabled?(:packages_protected_packages, package_protection_rule.project)
raise_resource_not_available_error!("'packages_protected_packages' feature flag is disabled")
end
response = ::Packages::Protection::DeleteRuleService.new(package_protection_rule,
current_user: current_user).execute

View File

@ -7,8 +7,7 @@ module Mutations
class Update < ::Mutations::BaseMutation
graphql_name 'UpdatePackagesProtectionRule'
description 'Updates a package protection rule to restrict access to project packages. ' \
'You can prevent users without certain permissions from altering packages. ' \
'Available only when feature flag `packages_protected_packages` is enabled.'
'You can prevent users without certain permissions from altering packages.'
authorize :admin_package
@ -49,10 +48,6 @@ module Mutations
def resolve(id:, **kwargs)
package_protection_rule = authorized_find!(id: id)
if Feature.disabled?(:packages_protected_packages, package_protection_rule.project)
raise_resource_not_available_error!("'packages_protected_packages' feature flag is disabled")
end
response = ::Packages::Protection::UpdateRuleService.new(package_protection_rule,
current_user: current_user, params: kwargs).execute

View File

@ -7,8 +7,6 @@ module Resolvers
alias_method :project, :object
def resolve(**_args)
return [] if Feature.disabled?(:packages_protected_packages, project)
project.package_protection_rules
end
end

View File

@ -25,10 +25,7 @@ module Types
field :project, Types::ProjectType, null: false, description: 'Project where the package is stored.'
field :protection_rule_exists, GraphQL::Types::Boolean,
null: false,
alpha: { milestone: '17.0' },
description:
'Whether any matching package protection rule exists for this package. ' \
'Available only when feature flag `packages_protected_packages` is enabled.'
description: 'Whether any matching package protection rule exists for the package.'
field :status, Types::Packages::PackageStatusEnum, null: false, description: 'Package status.'
field :status_message, GraphQL::Types::String, null: true, description: 'Status message.'
field :tags, Types::Packages::PackageTagType.connection_type, null: true, description: 'Package tags.'
@ -40,8 +37,6 @@ module Types
end
def protection_rule_exists
return false if Feature.disabled?(:packages_protected_packages, object.project)
object_package_type_value = ::Packages::Package.package_types[object.package_type]
BatchLoader::GraphQL.for([object.name, object_package_type_value]).batch do |inputs, loader|

View File

@ -9,8 +9,7 @@ module Types
value 'NPM',
value: 'npm',
alpha: { milestone: '16.5' },
description: "Packages of the npm format."
description: 'Packages of the npm format.'
value 'PYPI',
value: 'pypi',

View File

@ -36,7 +36,7 @@ module Projects
projectPath: project.full_path,
index_models_path: project_ml_models_path(project),
edit_model_path: edit_project_ml_model_path(project, model.id),
create_model_version_path: new_project_ml_model_version_path(project, model_model_id: model.id),
create_model_version_path: new_project_ml_model_version_path(project, model.id),
can_write_model_registry: can_write_model_registry?(user, project),
mlflow_tracking_url: mlflow_tracking_url(project),
model_id: model.id,
@ -91,6 +91,8 @@ module Projects
can_write_model_registry: can_write_model_registry?(user, project),
import_path: model_version_artifact_import_path(project.id, model_version.id),
model_path: project_ml_model_path(project, model_version.model),
edit_model_version_path: edit_project_ml_model_version_path(project, model_version.model.id,
model_version.id),
max_allowed_file_size: max_allowed_file_size(project),
markdown_preview_path: preview_markdown_path(project)
}
@ -98,6 +100,22 @@ module Projects
to_json(data)
end
def edit_ml_model_version_data(model_version, user)
project = model_version.project
data = {
projectPath: project.full_path,
can_write_model_registry: can_write_model_registry?(user, project),
markdown_preview_path: preview_markdown_path(project),
model_version_path: project_ml_model_version_path(project, model_version.model.id, model_version.id),
model_gid: model_version.model.to_global_id.to_s,
model_version_description: model_version.description.to_s,
model_version_version: model_version.version
}
to_json(data)
end
private
def model_version_artifact_import_path(project_id, model_version_id)

View File

@ -74,8 +74,6 @@ module Packages
end
def current_package_protected?
return false if Feature.disabled?(:packages_protected_packages, project)
unless current_user.is_a?(User)
return project.package_protection_rules.for_package_type(:npm).for_package_name(name).exists?
end

View File

@ -6,6 +6,7 @@
- page_title "#{@commit.title} (#{@commit.short_id})", _('Commits')
- page_description @commit.description
- add_page_specific_style 'page_bundles/pipelines'
- add_page_specific_style 'page_bundles/design_management'
.container-fluid{ class: [container_class] }
= render "commit_box"

View File

@ -0,0 +1,6 @@
- add_to_breadcrumbs s_('ModelRegistry|Model registry'), project_ml_models_path(@project)
- add_to_breadcrumbs @model_version.name, project_ml_model_path(@project, @model)
- breadcrumb_title @model_version.version
- page_title "#{@model_version.name} / #{@model_version.version}"
#js-mount-edit-ml-model-version{ data: { view_model: edit_ml_model_version_data(@model_version, @current_user) } }

View File

@ -5,19 +5,20 @@
- placeholder = model.is_a?(MergeRequest) ? _('Describe the goal of the changes and what reviewers should be aware of.') : _('Write a description or drag your files here…')
- no_issuable_templates = issuable_templates(ref_project, model.to_ability_name).empty?
- preview_url = preview_markdown_path(project, target_type: model.class.name)
- is_merge_request = model.is_a?(MergeRequest)
.form-group
.gl-flex
= form.label :description, _('Description'), class: 'gl-block'
- if is_merge_request
- if model.is_a?(MergeRequest)
= render_if_exists "/shared/form_elements/summarize_merge_request"
- if model.is_a?(MergeRequest)
= hidden_field_tag :merge_request_diff_head_sha, model.diff_head_sha
- if model.is_a?(Issuable)
= render 'shared/issuable/form/template_selector', issuable: model
= render 'shared/form_elements/apply_template_warning', issuable: model
- if is_merge_request
- if model.is_a?(MergeRequest)
= render 'shared/form_elements/apply_generated_description_warning', issuable: model
.js-markdown-editor{ data: { render_markdown_path: preview_url,
@ -26,11 +27,7 @@
testid: 'issuable-form-description-field',
form_field_placeholder: placeholder,
autofocus: 'false',
form_field_classes: 'js-gfm-input markdown-area note-textarea rspec-issuable-form-description',
project_id: @project.id,
source_branch: is_merge_request ? @merge_request.source_branch : nil,
target_branch: is_merge_request ? @merge_request.target_branch : nil,
can_summarize: is_merge_request ? can?(current_user, :summarize_new_merge_request, @project).to_s : nil } }
form_field_classes: 'js-gfm-input markdown-area note-textarea rspec-issuable-form-description' } }
= form.hidden_field :description
- if no_issuable_templates && can?(current_user, :push_code, model.project)

View File

@ -16,7 +16,7 @@
= icon_for_system_note(note)
- else
.timeline-avatar.gl-float-left
%a.image-diff-avatar-link{ href: user_path(note.author) }
%a.image-diff-avatar-link.gl-block{ href: user_path(note.author) }
= render Pajamas::AvatarComponent.new(note.author, size: 32, alt: '')
- if note.is_a?(DiffNote) && note.on_image?
- if show_image_comment_badge && note_counter == 0

View File

@ -1,8 +0,0 @@
---
name: packages_protected_packages
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/125915
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/416395
milestone: '16.5'
type: development
group: group::package registry
default_enabled: false

View File

@ -481,7 +481,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
resources :candidates, only: [:show, :destroy], controller: 'candidates', param: :iid
resources :models, only: [:index, :show, :edit, :destroy, :new], controller: 'models', param: :model_id do
resources :versions, only: [:new], controller: 'model_versions'
resources :versions, only: [:show], controller: 'model_versions', param: :model_version_id
resources :versions, only: [:show, :edit], controller: 'model_versions', param: :model_version_id
end
post :preview_markdown
end

View File

@ -135,7 +135,7 @@ To add a custom hostname after your instance is created, submit a [support ticke
### SMTP email service
You can configure an [SMTP](../../subscriptions/gitlab_dedicated/index.md#smtp) email service for your GitLab Dedicated instance.
You can configure an [SMTP](../../subscriptions/gitlab_dedicated/index.md#email-service) email service for your GitLab Dedicated instance.
To configure an SMTP email service, submit a [support ticket](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=4414917877650) with the credentials and settings for your SMTP server.

View File

@ -39,7 +39,8 @@ and all **secondary** sites:
to protect the disaster recovery (DR) capability of the **secondary** sites.
1. SSH into each node of the **primary** site.
1. [Upgrade GitLab on the **primary** site](../../../update/package/index.md#upgrade-using-the-official-repositories).
1. Perform testing on the **primary** site, particularly if you paused replication in step 1 to protect DR. [There are some suggestions for post-upgrade testing](../../../update/plan_your_upgrade.md#pre-upgrade-and-post-upgrade-checks) in the upgrade documentation.
1. Perform testing on the **primary** site, particularly if you paused replication in step 1 to protect DR.
[There are some suggestions for post-upgrade testing](../../../update/index.md#pre-upgrade-and-post-upgrade-checks) in the upgrade documentation.
1. Ensure that the secrets in the `/etc/gitlab/gitlab-secrets.json` file of both the primary site and the secondary site are the same. The file must be the same on all of a site's nodes.
1. SSH into each node of **secondary** sites.
1. [Upgrade GitLab on each **secondary** site](../../../update/package/index.md#upgrade-using-the-official-repositories).

View File

@ -264,7 +264,7 @@ When attempting `git push`, you can see:
This combination of errors occurs when the GitLab server has been upgraded to GitLab 15.5 or later but Gitaly has not yet been upgraded.
From GitLab 15.5, GitLab [authenticates with GitLab Shell using a JWT token instead of a shared secret](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/86148).
You should follow the [recommendations on upgrading external Gitaly](../../update/plan_your_upgrade.md#external-gitaly) and upgrade Gitaly before the GitLab
You should follow the [recommendations on upgrading external Gitaly](../../update/index.md#external-gitaly) and upgrade Gitaly before the GitLab
server.
## Repository pushes fail with a `deny updating a hidden ref` error

View File

@ -31,7 +31,7 @@ If you store data locally, see how to
## Supported object storage providers
GitLab is tightly integrated with the Fog library, so you can see which
[providers](https://fog.io/about/provider_documentation.html) can be used
[providers](https://fog.github.io/about/provider_documentation.html) can be used
with GitLab.
Specifically, GitLab has been tested by vendors and customers on a number of object storage providers:

View File

@ -3750,7 +3750,7 @@ Input type: `CreateNoteInput`
### `Mutation.createPackagesProtectionRule`
Creates a protection rule to restrict access to project packages. Available only when feature flag `packages_protected_packages` is enabled.
Creates a protection rule to restrict access to project packages.
DETAILS:
**Introduced** in GitLab 16.5.
@ -4319,7 +4319,7 @@ Input type: `DeleteContainerRegistryProtectionRuleInput`
### `Mutation.deletePackagesProtectionRule`
Deletes a protection rule for packages. Available only when feature flag `packages_protected_packages` is enabled.
Deletes a protection rule for packages.
DETAILS:
**Introduced** in GitLab 16.6.
@ -10115,7 +10115,7 @@ Input type: `UpdatePackagesCleanupPolicyInput`
### `Mutation.updatePackagesProtectionRule`
Updates a package protection rule to restrict access to project packages. You can prevent users without certain permissions from altering packages. Available only when feature flag `packages_protected_packages` is enabled.
Updates a package protection rule to restrict access to project packages. You can prevent users without certain permissions from altering packages.
DETAILS:
**Introduced** in GitLab 16.6.
@ -29250,7 +29250,7 @@ Represents a package with pipelines in the Package Registry.
| <a id="packagepackagetype"></a>`packageType` | [`PackageTypeEnum!`](#packagetypeenum) | Package type. |
| <a id="packagepipelines"></a>`pipelines` | [`PipelineConnection`](#pipelineconnection) | Pipelines that built the package. Max page size 20. (see [Connections](#connections)) |
| <a id="packageproject"></a>`project` | [`Project!`](#project) | Project where the package is stored. |
| <a id="packageprotectionruleexists"></a>`protectionRuleExists` **{warning-solid}** | [`Boolean!`](#boolean) | **Introduced** in GitLab 17.0. **Status**: Experiment. Whether any matching package protection rule exists for this package. Available only when feature flag `packages_protected_packages` is enabled. |
| <a id="packageprotectionruleexists"></a>`protectionRuleExists` | [`Boolean!`](#boolean) | Whether any matching package protection rule exists for the package. |
| <a id="packagestatus"></a>`status` | [`PackageStatus!`](#packagestatus) | Package status. |
| <a id="packagestatusmessage"></a>`statusMessage` | [`String`](#string) | Status message. |
| <a id="packagetags"></a>`tags` | [`PackageTagConnection`](#packagetagconnection) | Package tags. (see [Connections](#connections)) |
@ -29273,7 +29273,7 @@ Represents a package in the Package Registry.
| <a id="packagebasename"></a>`name` | [`String!`](#string) | Name of the package. |
| <a id="packagebasepackagetype"></a>`packageType` | [`PackageTypeEnum!`](#packagetypeenum) | Package type. |
| <a id="packagebaseproject"></a>`project` | [`Project!`](#project) | Project where the package is stored. |
| <a id="packagebaseprotectionruleexists"></a>`protectionRuleExists` **{warning-solid}** | [`Boolean!`](#boolean) | **Introduced** in GitLab 17.0. **Status**: Experiment. Whether any matching package protection rule exists for this package. Available only when feature flag `packages_protected_packages` is enabled. |
| <a id="packagebaseprotectionruleexists"></a>`protectionRuleExists` | [`Boolean!`](#boolean) | Whether any matching package protection rule exists for the package. |
| <a id="packagebasestatus"></a>`status` | [`PackageStatus!`](#packagestatus) | Package status. |
| <a id="packagebasestatusmessage"></a>`statusMessage` | [`String`](#string) | Status message. |
| <a id="packagebasetags"></a>`tags` | [`PackageTagConnection`](#packagetagconnection) | Package tags. (see [Connections](#connections)) |
@ -29344,7 +29344,7 @@ Represents a package details in the Package Registry.
| <a id="packagedetailstypepackagetype"></a>`packageType` | [`PackageTypeEnum!`](#packagetypeenum) | Package type. |
| <a id="packagedetailstypepipelines"></a>`pipelines` | [`PipelineConnection`](#pipelineconnection) | Pipelines that built the package. Max page size 20. (see [Connections](#connections)) |
| <a id="packagedetailstypeproject"></a>`project` | [`Project!`](#project) | Project where the package is stored. |
| <a id="packagedetailstypeprotectionruleexists"></a>`protectionRuleExists` **{warning-solid}** | [`Boolean!`](#boolean) | **Introduced** in GitLab 17.0. **Status**: Experiment. Whether any matching package protection rule exists for this package. Available only when feature flag `packages_protected_packages` is enabled. |
| <a id="packagedetailstypeprotectionruleexists"></a>`protectionRuleExists` | [`Boolean!`](#boolean) | Whether any matching package protection rule exists for the package. |
| <a id="packagedetailstypepublicpackage"></a>`publicPackage` | [`Boolean`](#boolean) | Indicates if there is public access to the package. |
| <a id="packagedetailstypepypisetupurl"></a>`pypiSetupUrl` | [`String`](#string) | Url of the PyPi project setup endpoint. |
| <a id="packagedetailstypepypiurl"></a>`pypiUrl` | [`String`](#string) | Url of the PyPi project endpoint. |
@ -38953,7 +38953,7 @@ Package type of a package protection rule resource.
| Value | Description |
| ----- | ----------- |
| <a id="packagesprotectionrulepackagetypenpm"></a>`NPM` **{warning-solid}** | **Introduced** in GitLab 16.5. **Status**: Experiment. Packages of the npm format. |
| <a id="packagesprotectionrulepackagetypenpm"></a>`NPM` | Packages of the npm format. |
| <a id="packagesprotectionrulepackagetypepypi"></a>`PYPI` **{warning-solid}** | **Introduced** in GitLab 17.6. **Status**: Experiment. Packages of the PyPI format. |
### `PipelineAnalyticsJobStatus`

View File

@ -10,16 +10,12 @@ description: "Documentation for the REST API for Package Protection Rules in Git
DETAILS:
**Tier:** Free, Premium, Ultimate
**Offering:** Self-managed
**Status:** Experiment
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/151741) in GitLab 17.1 [with a flag](../administration/feature_flags.md) named `packages_protected_packages`. Disabled by default.
> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/472655) in GitLab 17.5.
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/472655) in GitLab 17.6. Feature flag `packages_protected_packages` removed.
FLAG:
The availability of this feature is controlled by a feature flag.
For more information, see the history.
This feature is available for testing, but not ready for production use.
This API manages the protection rules for packages. This feature is an experiment.
This API manages the protection rules for packages.
## List package protection rules

View File

@ -7,80 +7,96 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# GitLab Dedicated
GitLab Dedicated is a fully isolated, single-tenant SaaS solution that is:
GitLab Dedicated is a single-tenant SaaS solution that is:
- Hosted and managed by GitLab, Inc.
- Deployed on AWS in a cloud [region](data_residency_and_high_availability.md#available-aws-regions) of your choice.
- Fully isolated.
- Deployed in your preferred AWS cloud region.
- Hosted and maintained by GitLab.
GitLab Dedicated removes the overhead of platform management to increase your operational efficiency, reduce risk, and enhance the speed and agility of your organization. Each GitLab Dedicated instance is highly available with disaster recovery and deployed into the cloud region of your choice. GitLab teams fully manage the maintenance and operations of each isolated instance, so customers can access our latest product improvements while meeting the most complex compliance standards.
Each instance provides:
It's the offering of choice for enterprises and organizations in highly regulated industries that have complex regulatory, compliance, and data residency requirements.
- [High availability](data_residency_and_high_availability.md) with disaster recovery.
- [Regular updates](maintenance.md) with the latest features.
- Enterprise-grade security measures.
With GitLab Dedicated, you can:
- Increase operational efficiency.
- Reduce infrastructure management overhead.
- Improve organizational agility.
- Meet strict compliance requirements.
## Available features
### Advanced search
GitLab Dedicated uses the [advanced search functionality](../../integration/advanced_search/elasticsearch.md).
This section lists the key features that are available for GitLab Dedicated.
### Security
GitLab Dedicated provides the following security features to protect your data and control access to your instance.
#### Authentication and authorization
GitLab Dedicated supports instance-level [SAML OmniAuth](../../integration/saml.md) functionality using a single SAML provider. Your GitLab Dedicated instance acts as the service provider, and you must provide the necessary [configuration](../../integration/saml.md#configure-saml-support-in-gitlab) in order for GitLab to communicate with your IdP. For more information, see how to [configure SAML](../../administration/dedicated/configure_instance.md#saml) for your instance.
You can configure [SAML single sign-on (SSO)](../../integration/saml.md) using a single SAML provider for authentication. Your instance acts as the service provider, and you provide the necessary configuration for GitLab to communicate with your Identity Provider (IdP). SAML request signing, group sync, and SAML groups are supported.
- SAML [request signing](../../integration/saml.md#sign-saml-authentication-requests-optional), [group sync](../../user/group/saml_sso/group_sync.md#configure-saml-group-sync), and [SAML groups](../../integration/saml.md#configure-users-based-on-saml-group-membership) are supported.
For more information, see how to configure [SAML](../../administration/dedicated/configure_instance.md#saml) for your instance.
#### Secure networking
GitLab Dedicated offers public connectivity by default with support for IP allowlists. You can [optionally specify a list of IP addresses](../../administration/dedicated/configure_instance.md#ip-allowlist) that can access your GitLab Dedicated instance. Subsequently, when an IP not on the allowlist tries to access your instance the connection is refused.
Two connectivity options are available:
Private connectivity using [AWS PrivateLink](https://aws.amazon.com/privatelink/) is also offered as an option. Both [inbound](../../administration/dedicated/configure_instance.md#inbound-private-link) and [outbound](../../administration/dedicated/configure_instance.md#outbound-private-link) PrivateLinks are supported. When connecting to internal resources over an outbound PrivateLink with non public certificates, you can specify a list of certificates that are trusted by GitLab. These certificates can be provided when [updating your instance configuration](../../administration/dedicated/configure_instance.md#custom-certificates).
- Public connectivity with IP allowlists: By default, your instance is publicly accessible. You can [configure an IP allowlist](../../administration/dedicated/configure_instance.md#ip-allowlist) to restrict access to specified IP addresses.
- Private connectivity with AWS PrivateLink: You can configure [AWS PrivateLink](https://aws.amazon.com/privatelink/) for [inbound](../../administration/dedicated/configure_instance.md#inbound-private-link) and [outbound](../../administration/dedicated/configure_instance.md#outbound-private-link) connections.
#### Encryption
For private connections to internal resources using non-public certificates, you can also [specify trusted certificates](../../administration/dedicated/configure_instance.md#custom-certificates).
#### Data encryption
Data is encrypted at rest and in transit using the latest encryption standards.
#### Bring your own key encryption
Optionally, you can use your own AWS Key Management Service (KMS) encryption key for data at rest. This option gives you full control over the data you store in GitLab.
During onboarding, you can specify an AWS KMS encryption key stored in your own AWS account that GitLab uses to encrypt the data for your Dedicated instance. This gives you full control over the data you store in GitLab.
For more information, see [Encrypted data at rest (BYOK)](../../administration/dedicated/create_instance.md#encrypted-data-at-rest-byok).
#### SMTP
#### Email service
Email sent from GitLab Dedicated uses [Amazon Simple Email Service (Amazon SES)](https://aws.amazon.com/ses/). The connection to Amazon SES is encrypted.
By default, [Amazon Simple Email Service (Amazon SES)](https://aws.amazon.com/ses/) is used to send emails securely. As an alternative, you can [configure your own email service](../../administration/dedicated/configure_instance.md#smtp-email-service) using SMTP.
If you would rather send application email using an SMTP server instead of Amazon SES, you can [configure your own email service](../../administration/dedicated/configure_instance.md#smtp-email-service).
### Compliance
### Compliance and certifications
GitLab Dedicated adheres to various regulations, certifications, and compliance frameworks to ensure the security, and reliability of your data.
GitLab Dedicated is trusted by highly regulated customers in part due to our ability to transparently demonstrate compliance with various regulations, certifications, and compliance frameworks.
#### View compliance and certification details
You can view compliance and certification details, and download compliance artifacts from the [GitLab Dedicated Trust Center](https://trust.gitlab.com/?product=gitlab-dedicated).
#### Access controls
GitLab Dedicated adheres to the
[principle of least privilege](https://handbook.gitlab.com/handbook/security/access-management-policy/#principle-of-least-privilege)
to control access to customer tenant environments. Tenant AWS accounts live under
a top-level GitLab Dedicated AWS parent organization. Access to the AWS Organization
is restricted to select GitLab team members. All user accounts within the AWS Organization
follow the overall [GitLab Access Management Policy](https://handbook.gitlab.com/handbook/security/access-management-policy/).
Direct access to customer tenant environments is restricted to a single Hub account.
The GitLab Dedicated Control Plane uses the Hub account to perform automated actions
over tenant accounts when managing environments. Similarly, GitLab Dedicated engineers
do not have direct access to customer tenant environments.
In [break glass](https://gitlab.com/gitlab-com/gl-infra/gitlab-dedicated/team/-/blob/main/engineering/breaking_glass.md)
situations, where access to resources in the tenant environment is required to
address a high-severity issue, GitLab engineers must go through the Hub account
to manage those resources. This is done via an approval process, and after permission
is granted, the engineer will assume an IAM role on a temporary basis to access
tenant resources through the Hub account. All actions within the hub account and
tenant account are logged to CloudTrail.
GitLab Dedicated implements strict access controls to protect your environment:
Inside tenant accounts, GitLab leverages Intrusion Detection and Malware Scanning capabilities from AWS GuardDuty. Infrastructure logs are monitored by the GitLab Security Incident Response Team to detect anomalous events.
- Follows the [principle of least privilege](https://handbook.gitlab.com/handbook/security/access-management-policy/#principle-of-least-privilege).
- Restricts access to the AWS organization to select GitLab team members.
- User accounts follow the [Access Management Policy](https://handbook.gitlab.com/handbook/security/access-management-policy/).
- Uses a single Hub account for automated actions and emergency access.
- GitLab Dedicated engineers do not have direct access to customer environments.
In [emergency situations](https://gitlab.com/gitlab-com/gl-infra/gitlab-dedicated/incident-management/-/blob/main/procedures/break-glass.md#break-glass-procedure), GitLab engineers must:
1. Use the Hub account to access customer resources.
1. Request access through an approval process.
1. Assume a temporary IAM role through the Hub account.
All actions in the Hub and tenant accounts are logged to CloudTrail.
#### Monitoring
In tenant accounts, GitLab Dedicated uses:
- AWS GuardDuty for intrusion detection and malware scanning.
- Infrastructure log monitoring by the GitLab Security Incident Response Team to detect anomalous events.
#### Audit and observability
GitLab Dedicated provides access to [application logs](../../administration/dedicated/configure_instance.md#application-logs).
You can access [application logs](../../administration/dedicated/configure_instance.md#application-logs) for auditing and observability purposes. These logs provide insights into system activities and user actions, helping you monitor your instance and maintain compliance requirements.
### Bring your own domain
@ -103,7 +119,11 @@ Custom hostnames for GitLab Pages are not supported. If you use GitLab Pages, th
### Application
GitLab Dedicated comes with the self-managed [Ultimate feature set](https://about.gitlab.com/pricing/feature-comparison/) with the exception of the [unsupported features](#features-that-are-not-available) listed below.
GitLab Dedicated comes with the self-managed [Ultimate feature set](https://about.gitlab.com/pricing/feature-comparison/) with the exception of the [Unavailable features](#unavailable-features) listed below.
#### Advanced search
GitLab Dedicated uses the [advanced search functionality](../../integration/advanced_search/elasticsearch.md).
#### GitLab Pages
@ -146,16 +166,6 @@ To use self-managed runners, install [GitLab Runner](https://docs.gitlab.com/run
You can use [GitLab as an OpenID Connect identity provider](../../integration/openid_connect_provider.md). If you use an IP allowlist to restrict access to your instance, you can [enable OpenID Connect requests](../../administration/dedicated/configure_instance.md#enable-openid-connect-for-your-ip-allowlist) while maintaining your IP restrictions.
#### Migration
To help you migrate your data to GitLab Dedicated, choose from the following options:
1. When migrating from another GitLab instance, you can import groups and projects by either:
- Using [direct transfer](../../user/group/import/index.md).
- Using the [direct transfer](../../api/bulk_imports.md) API.
1. When migrating from third-party services, you can use [the GitLab importers](../../user/project/import/index.md#supported-import-sources).
1. You can also engage [Professional Services](../../user/project/import/index.md#migrate-by-engaging-professional-services).
### Pre-production environments
GitLab Dedicated supports pre-production environments that match the configuration of production environments. You can use pre-production environments to:
@ -176,31 +186,34 @@ Limitations:
- No SLA commitment.
- Cannot run newer versions than production.
## Features that are not available
## Unavailable features
### GitLab application features
This section lists the features that are not available for GitLab Dedicated.
### Application features
The following GitLab application features are not available:
- LDAP, smart card, or Kerberos authentication
- Multiple login providers
- FortiAuthenticator, or FortiToken 2FA
- Reply-by email
- FortiAuthenticator or FortiToken 2FA
- Reply by email
- Service Desk
- Some GitLab Duo AI capabilities
- View the [list of AI features to see which ones are supported](../../user/ai_features.md).
- Refer to our [direction page](https://about.gitlab.com/direction/saas-platforms/dedicated/#supporting-ai-features-on-gitlab-dedicated) for more information.
- View the [list of supported AI features](../../user/ai_features.md)
- For more information, see the [Supporting AI Features on GitLab Dedicated](https://about.gitlab.com/direction/saas-platforms/dedicated/#supporting-ai-features-on-gitlab-dedicated)
- Features other than [available features](#available-features) that must be configured outside of the GitLab user interface
- Any functionality or feature behind a Feature Flag that is toggled `off` by default.
- Any functionality or feature behind a feature flag that is turned `off` by default
The following features will not be supported:
The following features are not supported:
- Mattermost
- [Server-side Git hooks](../../administration/server_hooks.md).
GitLab Dedicated is a SaaS service, and access to the underlying infrastructure is only available to GitLab Inc. team members. Due to the nature of server side configuration, there is a possible security concern of running arbitrary code on Dedicated services, as well as the possible impact that can have on the service SLA. Use the alternative [push rules](../../user/project/repository/push_rules.md) or [webhooks](../../user/project/integrations/webhooks.md) instead.
- Interacting with GitLab [Feature Flags](../../administration/feature_flags.md). [Feature flags support the development and rollout of new or experimental features](https://handbook.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle/#when-to-use-feature-flags) on GitLab.com. Features behind feature flags are not considered ready for production use, are experimental and therefore unsafe for GitLab Dedicated. Stability and SLAs may be affected by changing default settings.
- [Mattermost](../../integration/mattermost/index.md)
- [Server-side Git hooks](../../administration/server_hooks.md)
### GitLab Dedicated service features
NOTE:
Access to the underlying infrastructure is only available to GitLab team members. Due to the server-side configuration, there is a security concern with running arbitrary code on services, and the possible impact on the service SLA. As an alternative, use [push rules](../../user/project/repository/push_rules.md) or [webhooks](../../user/project/integrations/webhooks.md) instead.
### Operational features
The following operational features are not available:
@ -209,13 +222,28 @@ The following operational features are not available:
- Self-serve purchasing and configuration
- Multiple login providers
- Support for deploying to non-AWS cloud providers, such as GCP or Azure
- Observability Dashboard using Switchboard
- Observability dashboard in Switchboard
## Planned features
### Feature flags
For more information about the planned improvements to GitLab Dedicated,
see the [category direction page](https://about.gitlab.com/direction/saas-platforms/dedicated/).
[Feature flags](../../administration/feature_flags.md) are not available for GitLab Dedicated.
## Interested in GitLab Dedicated?
Feature flags support the development and rollout of new or experimental features on GitLab.com. Features behind feature flags are not considered ready for production use, are experimental and therefore unsafe for GitLab Dedicated. Stability and SLAs may be affected by changing default settings.
Learn more about GitLab Dedicated and [talk to an expert](https://about.gitlab.com/dedicated/).
## Migrate to GitLab Dedicated
To migrate your data to GitLab Dedicated:
- From another GitLab instance:
- Use [direct transfer](../../user/group/import/index.md).
- Use the [direct transfer API](../../api/bulk_imports.md).
- From third-party services:
- Use [the import sources](../../user/project/import/index.md#supported-import-sources).
- For complex migrations:
- Engage [Professional Services](../../user/project/import/index.md#migrate-by-engaging-professional-services).
## Get started
For more information about GitLab Dedicated or to request a demo, see [GitLab Dedicated](https://about.gitlab.com/solutions/gitlab-dedicated/).
For more information on setting up your GitLab Dedicated instance, see [Create your GitLab Dedicated instance](../../administration/dedicated/create_instance.md).

90
doc/topics/git/project.md Normal file
View File

@ -0,0 +1,90 @@
---
stage: Data Stores
group: Tenant Scale
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"
---
# Create a project with `git push`
DETAILS:
**Tier:** Free, Premium, Ultimate
**Offering:** GitLab.com, Self-managed, GitLab Dedicated
You can use `git push` to add a local project repository to GitLab. After you add a repository,
GitLab creates your project in your chosen namespace.
NOTE:
You cannot use `git push` to create projects with paths that were previously used or
[renamed](../../user/project/working_with_projects.md#rename-a-repository).
Previously used project paths have a redirect. Instead of creating a new project,
the redirect causes push attempts to redirect requests to the renamed project location.
To create a new project for a previously used or renamed project, use the UI
or the [Projects API](../../api/projects.md#create-a-project).
Prerequisites:
<!--- To push with SSH, you must have [an SSH key](../ssh.md) that is
[added to your GitLab account](../ssh.md#add-an-ssh-key-to-your-gitlab-account).
-->
- You must have permission to add new projects to a [namespace](../../user/namespace/index.md).
To verify your permissions:
1. On the left sidebar, select **Search or go to** and find your group.
1. In the upper-right corner, confirm that **New project** is visible.
If you do not have the necessary permission, contact your GitLab administrator.
To create a project with `git push`:
1. Push your local repository to GitLab with one of the following:
- With SSH:
- If your project uses the standard port 22, run:
```shell
git push --set-upstream git@gitlab.example.com:namespace/myproject.git main
```
- If your project requires a non-standard port number, run:
```shell
git push --set-upstream ssh://git@gitlab.example.com:00/namespace/myproject.git main
```
- With HTTP, run:
```shell
git push --set-upstream https://gitlab.example.com/namespace/myproject.git master
```
Replace the following values:
- `gitlab.example.com` with the machine domain name hosts your Git repository.
- `namespace` with your [namespace](../../user/namespace/index.md) name.
- `myproject` with your project name.
- If specifying a port, change `00` to your project's required port number.
- Optional. To export existing repository tags, append the `--tags` flag to
your `git push` command.
1. Optional. Configure the remote:
```shell
git remote add origin https://gitlab.example.com/namespace/myproject.git
```
When the `git push` operation completes, GitLab displays the following message:
```shell
remote: The private project namespace/myproject was created.
```
To view your new project, go to `https://gitlab.example.com/namespace/myproject`.
By default, your project's visibility is set to **Private**,
but you can [change the project's visibility](../../user/public_access.md#change-project-visibility).
## Related topics
- [Create a blank project](../../user/project/index.md)
- [Create a project from a template](../../user/project/index.md#create-a-project-from-a-built-in-template)
- [Clone a repository to your local machine](clone.md)

View File

@ -2,18 +2,23 @@
stage: none
group: none
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
noindex: false
---
# Breaking change windows
# Breaking change deployments on GitLab.com
Changes are deployed continuously to GitLab.com. However, breaking changes
can require more time to prepare for.
In the month before the GitLab 18.0 release, breaking changes will be deployed
during three time windows. The following tables list when each breaking change will be deployed.
<!--
Do not edit this page directly.
This page is generated by lib/tasks/gitlab/docs/compile_windows.rake and
from the yaml files in /data/deprecations.
To update this file, run: bin/rake gitlab:docs:compile_windows
-->
GitLab.com has breaking changes that will be deployed during the following windows.
## Window 1
This window takes place on April 21 - 23, 2025 from 09:00 UTC to 22:00 UTC.

View File

@ -5,7 +5,7 @@ description: Latest version instructions.
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
---
# Upgrade GitLab
# Upgrading GitLab
DETAILS:
**Tier:** Free, Premium, Ultimate
@ -17,20 +17,39 @@ Upgrading GitLab is a relatively straightforward process, but the complexity can
- How old your GitLab version is.
- If you're upgrading to a major version.
If possible, you should test out the upgrade in a test environment before updating your production instance. Your test
environment should mimic your production environment as closely as possible.
Make sure to read the whole page as it contains information related to every upgrade method.
## Upgrade GitLab
To upgrade GitLab:
1. Create an [upgrade plan](plan_your_upgrade.md) to document your upgrade steps.
1. Familiarize yourself with the [maintenance policy documentation](../policy/maintenance.md).
1. Read the [release posts](https://about.gitlab.com/releases/categories/releases/) for versions you're passing over.
In particular, deprecations, removals, and important notes on upgrading.
1. Check for [background migrations](background_migrations.md).
1. [Plan your upgrade](plan_your_upgrade.md).
1. Determine what [upgrade path](upgrade_paths.md) you should take. Your upgrade might require multiple upgrades. If
relevant, check [OS compatibility with the target GitLab version](../administration/package_information/supported_os.md).
1. Check for [background migrations](background_migrations.md). All migrations must finish running before each upgrade.
1. If available in your starting version, consider [turning on maintenance mode](../administration/maintenance_mode/index.md)
during the upgrade.
1. Consult changes for different versions of GitLab to ensure compatibility before upgrading:
- [GitLab 17 changes](versions/gitlab_17_changes.md)
- [GitLab 16 changes](versions/gitlab_16_changes.md)
- [GitLab 15 changes](versions/gitlab_15_changes.md)
1. Perform [pre-upgrade checks](#pre-upgrade-and-post-upgrade-checks).
1. Pause [running CI/CD pipelines and jobs](#cicd-pipelines-and-jobs-during-upgrades).
1. Follow [upgrade steps for additional features](#upgrade-steps-for-additional-features), if relevant.
1. Follow the [upgrade steps based on your installation method](#upgrade-based-on-installation-method).
1. If your GitLab instance has any runners associated with it, upgrade them to match the current GitLab version.
This step ensures [compatibility with GitLab versions](https://docs.gitlab.com/runner/#gitlab-runner-versions).
1. If you encounter problems with the upgrade, [get support](#getting-support).
1. [Disable maintenance mode](../administration/maintenance_mode/index.md#disable-maintenance-mode) if you had enabled
it.
1. Unpause [running CI/CD pipelines and jobs](#cicd-pipelines-and-jobs-during-upgrades).
1. Perform [post-upgrade checks](#pre-upgrade-and-post-upgrade-checks).
## Upgrade based on installation method
@ -88,7 +107,45 @@ can still be found in the Git repository:
::EndTabs
## Dealing with running CI/CD pipelines and jobs
## Pre-upgrade and post-upgrade checks
Immediately before and after the upgrade, perform the pre-upgrade and post-upgrade checks
to ensure the major components of GitLab are working:
1. [Check the general configuration](../administration/raketasks/maintenance.md#check-gitlab-configuration):
```shell
sudo gitlab-rake gitlab:check
```
1. Confirm that encrypted database values [can be decrypted](../administration/raketasks/check.md#verify-database-values-can-be-decrypted-using-the-current-secrets):
```shell
sudo gitlab-rake gitlab:doctor:secrets
```
1. In GitLab UI, check that:
- Users can sign in.
- The project list is visible.
- Project issues and merge requests are accessible.
- Users can clone repositories from GitLab.
- Users can push commits to GitLab.
1. For GitLab CI/CD, check that:
- Runners pick up jobs.
- Docker images can be pushed and pulled from the registry.
1. If using Geo, run the relevant checks on the primary and each secondary:
```shell
sudo gitlab-rake gitlab:geo:check
```
1. If using Elasticsearch, verify that searches are successful.
If something goes wrong, [get support](#getting-support).
## CI/CD pipelines and jobs during upgrades
If you upgrade your GitLab instance while the GitLab Runner is processing jobs, the trace updates fail. When GitLab is back online, the trace updates should self-heal. However, depending on the error, the GitLab Runner either retries, or eventually terminates, job handling.
@ -148,6 +205,58 @@ To downgrade your Enterprise Edition installation back to Community
Edition, you can follow [this guide](../downgrade_ee_to_ce/index.md) to make the process as smooth as
possible.
## Upgrade steps for additional features
Some GitLab features have additional steps.
### External Gitaly
If you're using an external Gitaly server, it must be upgraded to the newer
version prior to upgrading the application server.
### Geo
If you're using Geo:
- Review [Geo upgrade documentation](../administration/geo/replication/upgrading_the_geo_sites.md).
- Read about the Geo version-specific update instructions:
- [GitLab 17](versions/gitlab_17_changes.md)
- [GitLab 16](versions/gitlab_16_changes.md)
- [GitLab 15](versions/gitlab_15_changes.md)
- Review Geo-specific steps when [upgrading the database](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance).
- Create an upgrade and rollback plan for _each_ Geo site (primary and each secondary).
### GitLab agent for Kubernetes
If you have Kubernetes clusters connected with GitLab, [upgrade your GitLab agents for Kubernetes](../user/clusters/agent/install/index.md#update-the-agent-version) to match your new GitLab version.
### Elasticsearch
Before updating GitLab, confirm advanced search migrations are complete by
[checking for pending advanced search migrations](background_migrations.md#check-for-pending-advanced-search-migrations).
After updating GitLab, you may have to upgrade
[Elasticsearch if the new version breaks compatibility](../integration/advanced_search/elasticsearch.md#version-requirements).
Updating Elasticsearch is **out of scope for GitLab Support**.
## Getting support
If something goes wrong:
- Copy any errors and gather any logs to later analyze, and then [roll back to the last working version](plan_your_upgrade.md#rollback-plan).
You can use the following tools to help you gather data:
- [`gitlabsos`](https://gitlab.com/gitlab-com/support/toolbox/gitlabsos) if
you installed GitLab using the Linux package or Docker.
- [`kubesos`](https://gitlab.com/gitlab-com/support/toolbox/kubesos/) if
you installed GitLab using the Helm Charts.
For support:
- [Contact GitLab Support](https://support.gitlab.com/hc/en-us) and, if you have one, your Customer Success Manager.
- If [the situation qualifies](https://about.gitlab.com/support/#definitions-of-support-impact) and
[your plan includes emergency support](https://about.gitlab.com/support/#priority-support),
create an emergency ticket.
## Related topics
- [Managing PostgreSQL extensions](../install/postgresql_extensions.md)

View File

@ -4,67 +4,36 @@ 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
---
# Create a GitLab upgrade plan
# Create an upgrade plan
DETAILS:
**Tier:** Free, Premium, Ultimate
**Offering:** Self-managed
This document serves as a guide to create a strong plan to upgrade a self-managed
GitLab instance.
Creating an upgrade plan involves documenting:
General notes:
- The steps to take to upgrade your GitLab self-managed instance.
- The steps to take if the upgrade doesn't go smoothly.
- If possible, you should test out the upgrade in a test environment before
updating your production instance. Ideally, your test environment should mimic
your production environment as closely as possible.
- If [working with Support](https://about.gitlab.com/support/scheduling-upgrade-assistance/)
to create your plan, share details of your architecture, including:
- How is GitLab installed?
- What is the operating system of the node?
(check [OS versions that are no longer supported](../administration/package_information/supported_os.md#os-versions-that-are-no-longer-supported) to confirm that later updates are available).
- Is it a single-node or a multi-node setup? If multi-node, share any architectural details about each node with us.
- Are you using [GitLab Geo](../administration/geo/index.md)? If so, share any architectural details about each secondary node.
- What else might be unique or interesting in your setup that might be important for us to understand?
- Are you running into any known issues with your current version of GitLab?
Your upgrade plan should include:
## Pre-upgrade and post-upgrade checks
- How to upgrade GitLab including, if possible and required, a [zero-downtime upgrade](zero_downtime.md).
- How to [roll back GitLab](#rollback-plan), if necessary.
Immediately before and after the upgrade, perform the pre-upgrade and post-upgrade checks
to ensure the major components of GitLab are working:
## Working with Support
1. [Check the general configuration](../administration/raketasks/maintenance.md#check-gitlab-configuration):
If you are [working with Support](https://about.gitlab.com/support/scheduling-upgrade-assistance/) to review your
upgrade plan, document and share it with the answers to the following questions:
```shell
sudo gitlab-rake gitlab:check
```
1. Confirm that encrypted database values [can be decrypted](../administration/raketasks/check.md#verify-database-values-can-be-decrypted-using-the-current-secrets):
```shell
sudo gitlab-rake gitlab:doctor:secrets
```
1. In GitLab UI, check that:
- Users can sign in.
- The project list is visible.
- Project issues and merge requests are accessible.
- Users can clone repositories from GitLab.
- Users can push commits to GitLab.
1. For GitLab CI/CD, check that:
- Runners pick up jobs.
- Docker images can be pushed and pulled from the registry.
1. If using Geo, run the relevant checks on the primary and each secondary:
```shell
sudo gitlab-rake gitlab:geo:check
```
1. If using Elasticsearch, verify that searches are successful.
If in any case something goes wrong, see [how to troubleshoot](#troubleshooting).
- How is GitLab installed?
- What is the operating system of the node? Check [OS versions that are no longer supported](../administration/package_information/supported_os.md#os-versions-that-are-no-longer-supported)
to confirm that later updates are available.
- Is it a single-node or a multi-node setup? If multi-node, document and share any architectural details about each node.
Which external components are used? For example, Gitaly, PostgreSQL, or Redis?
- Are you using [GitLab Geo](../administration/geo/index.md)? If so, document and share any architectural details about
each secondary node.
- What else might be unique or interesting in your setup that might be important?
- Are you running into any known issues with your current version of GitLab?
## Rollback plan
@ -100,96 +69,3 @@ To restore your GitLab backup:
Confirm that the [secrets and configuration files](../administration/backup_restore/backup_gitlab.md#storing-configuration-files) are also restored.
- If restoring from a snapshot, know the steps to do this.
**This process is out of scope for GitLab Support.**
## Upgrade plan
For the upgrade plan, start by creating an outline of a plan that best applies
to your instance and then upgrade it for any relevant features you're using.
- Generate an upgrade plan by reading and understanding the relevant documentation:
- Upgrade based on the [installation method](index.md#upgrade-based-on-installation-method).
- [Zero-downtime upgrades](zero_downtime.md) (if possible and desired)
- [Convert from GitLab Community Edition to Enterprise Edition](package/convert_to_ee.md)
- What version should you upgrade to:
- [Determine what upgrade path](upgrade_paths.md) to follow.
- Account for changes in GitLab versions. For more information, see:
- [GitLab 17 changes](versions/gitlab_17_changes.md)
- [GitLab 16 changes](versions/gitlab_16_changes.md)
- [GitLab 15 changes](versions/gitlab_15_changes.md)
- Check the [OS compatibility with the target GitLab version](../administration/package_information/supported_os.md).
- Check for required database and advanced search [background migrations](background_migrations.md). If there are
background migrations, pause before any further upgrades. All migrations must finish running before the next
upgrade.
- If your GitLab instance has any runners associated with it, you must upgrade them to match the current GitLab version.
This ensures [compatibility with GitLab versions](https://docs.gitlab.com/runner/#gitlab-runner-versions).
- If available in your starting version, consider
[turning on maintenance mode](../administration/maintenance_mode/index.md) during the
upgrade.
- About PostgreSQL:
1. On the left sidebar, at the bottom, select **Admin**.
1. Look for the version of PostgreSQL you are using.
If [a PostgreSQL upgrade is needed](../administration/package_information/postgresql_versions.md),
account for the relevant
[packaged](https://docs.gitlab.com/omnibus/settings/database.html#upgrade-packaged-postgresql-server)
or [non-packaged](https://docs.gitlab.com/omnibus/settings/database.html#upgrade-a-non-packaged-postgresql-database) steps.
### Additional features
Apart from all the generic information above, you may have enabled some features
that require special planning.
Feel free to ignore sections about features that are inapplicable to your setup,
such as Geo, external Gitaly, or Elasticsearch.
#### External Gitaly
If you're using an external Gitaly server, it must be upgraded to the newer
version prior to upgrading the application server.
#### Geo
If you're using Geo:
- Review [Geo upgrade documentation](../administration/geo/replication/upgrading_the_geo_sites.md).
- Read about the Geo version-specific update instructions:
- [GitLab 17](versions/gitlab_17_changes.md)
- [GitLab 16](versions/gitlab_16_changes.md)
- [GitLab 15](versions/gitlab_15_changes.md)
- Review Geo-specific steps when [upgrading the database](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance).
- Create an upgrade and rollback plan for _each_ Geo site (primary and each secondary).
#### Runners
After updating GitLab, upgrade your runners to match
[your new GitLab version](https://docs.gitlab.com/runner/#gitlab-runner-versions).
#### GitLab agent for Kubernetes
If you have Kubernetes clusters connected with GitLab, [upgrade your GitLab agents for Kubernetes](../user/clusters/agent/install/index.md#update-the-agent-version) to match your new GitLab version.
#### Elasticsearch
Before updating GitLab, confirm advanced search migrations are complete by
[checking for pending advanced search migrations](background_migrations.md#check-for-pending-advanced-search-migrations).
After updating GitLab, you may have to upgrade
[Elasticsearch if the new version breaks compatibility](../integration/advanced_search/elasticsearch.md#version-requirements).
Updating Elasticsearch is **out of scope for GitLab Support**.
## Troubleshooting
If anything doesn't go as planned:
- If time is of the essence, copy any errors and gather any logs to later analyze,
and then [roll back to the last working version](#rollback-plan). You can use
the following tools to help you gather data:
- [`gitlabsos`](https://gitlab.com/gitlab-com/support/toolbox/gitlabsos) if
you installed GitLab using the Linux package or Docker.
- [`kubesos`](https://gitlab.com/gitlab-com/support/toolbox/kubesos/) if
you installed GitLab using the Helm Charts.
- For support:
- [Contact GitLab Support](https://support.gitlab.com/hc/en-us) and,
if you have one, your Customer Success Manager.
- If [the situation qualifies](https://about.gitlab.com/support/#definitions-of-support-impact)
and [your plan includes emergency support](https://about.gitlab.com/support/#priority-support),
create an emergency ticket.

View File

@ -117,16 +117,7 @@ When GitLab Duo is turned off for a group, project, or instance:
- GitLab Duo features that access resources, like code, issues, and vulnerabilities, are not available.
- Code Suggestions is not available.
However, GitLab Duo Chat works differently. When you turn off GitLab Duo:
- For a group or project:
- You can still ask questions of GitLab Duo Chat. These questions must be generic, like
asking about GitLab or asking general questions about code. GitLab Duo Chat will not access group or
project resources, and will reject questions about them.
- For an instance:
- The **GitLab Duo Chat** button is not available anywhere in the UI.
- Duo Chat is not available.
### Turn off for a group

View File

@ -10,8 +10,12 @@ GitLab Duo Chat can be turned on and off, and availability changed.
## For GitLab.com
For a limited time, GitLab Duo Chat is automatically available for all GitLab.com users
who are members of at least one group with a Premium or Ultimate subscription.
In GitLab 16.11 and later, GitLab Duo Chat is:
- Generally available.
- Available to any user with an assigned GitLab Duo seat.
If you [turn on or turn off GitLab Duo](../gitlab_duo/turn_on_off.md), you turn on or turn off Duo Chat as well.
## For self-managed
@ -31,10 +35,10 @@ Then, depending on the version of GitLab you have, you can enable GitLab Duo Cha
### In GitLab 16.11 and later
In GitLab 16.11 and later, GitLab Duo Chat is generally available
and automatically enabled for all users who have a subscription to the Premium or Ultimate tier.
In GitLab 16.11 and later, GitLab Duo Chat is:
You do not need to do anything to enable GitLab Duo Chat if you have GitLab 16.11 or later.
- Generally available.
- Available to any user with an assigned GitLab Duo seat.
### In earlier GitLab versions

View File

@ -336,3 +336,13 @@ if they have the same or a higher role in the parent group.
To view and update direct memberships, [filter the group to show direct members](index.md#filter-a-group).
[Issue 337539](https://gitlab.com/gitlab-org/gitlab/-/issues/337539#note_1277786161) proposes a redesigned members page that lists both direct and indirect memberships with the ability to filter by type.
### Cannot clone or pull using SSH after enabling IP restrictions
If you have issues with Git SSH operations after adding IP address restrictions,
check if your connection defaults to IPv6.
Some operating systems prioritize IPv6 over IPv4 when both are available,
which might not be obvious from the Git terminal feedback.
If your connection uses IPv6, you can resolve this issue by adding the IPv6 address to the allowlist.

View File

@ -9,15 +9,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w
DETAILS:
**Tier:** Free, Premium, Ultimate
**Offering:** GitLab.com, Self-managed
**Status:** Experiment
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/416395) in GitLab 16.5 [with a flag](../../../administration/feature_flags.md) named `packages_protected_packages`. Disabled by default. This feature is an [experiment](../../../policy/experiment-beta-support.md).
> - **Push protected up to access level** setting [changed](https://gitlab.com/gitlab-org/gitlab/-/issues/416382) to **Minimum access level for push** in GitLab 17.1.
FLAG:
The availability of this feature is controlled by a feature flag.
For more information, see the history.
This feature is available for testing, but not ready for production use.
> - The protection rule setting **Push protected up to access level** [renamed](https://gitlab.com/gitlab-org/gitlab/-/issues/416382) to **Minimum access level for push** in GitLab 17.1
> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/472655) in GitLab 17.5.
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/472655) in GitLab 17.6. Feature flag `packages_protected_packages` removed.
By default, any user with at least the Developer role can create,
edit, and delete packages. Add a package protection rule to restrict

View File

@ -11,7 +11,7 @@ DETAILS:
**Offering:** GitLab.com, Self-managed, GitLab Dedicated
You have different options to create a project. You can create a blank project, create a project
from built-in or custom templates, or create a project with `git push`.
from built-in or custom templates, or [create a project with `git push`](../../topics/git/project.md).
## Create a blank project
@ -154,75 +154,9 @@ Federal regulations, such as NIST and CISA [guidelines](https://csrc.nist.gov/pr
which [FedRamp](https://www.fedramp.gov/) enforces, have set a due date in 2030 to stop using SHA-1 and
encourage agencies to move away from SHA-1 earlier, if possible.
## Create a project with `git push`
Use `git push` to add a local project repository to GitLab. After you add a repository,
GitLab creates your project in your chosen namespace.
You cannot use `git push` to create projects with paths that have been used previously
or [renamed](working_with_projects.md#rename-a-repository).
Previously used project paths have a redirect. Instead of creating a new project, the redirect causes
push attempts to redirect requests to the renamed project location.
To create a new project for a previously used or renamed project, use the UI or the [Projects API](../../api/projects.md#create-a-project).
Prerequisites:
- To push with SSH, you must have [an SSH key](../ssh.md) that is
[added to your GitLab account](../ssh.md#add-an-ssh-key-to-your-gitlab-account).
- You must have permission to add new projects to a namespace. To check if you have permission:
1. On the left sidebar, select **Search or go to** and find your group.
1. In the upper-right corner, confirm that **New project** is visible.
If you do not have the necessary permission, contact your GitLab administrator.
To create a project with `git push`:
1. In your local repository, push either:
- With SSH, by running:
```shell
# Use this version if your project uses the standard port 22
$ git push --set-upstream git@gitlab.example.com:namespace/myproject.git main
# Use this version if your project requires a non-standard port number
$ git push --set-upstream ssh://git@gitlab.example.com:00/namespace/myproject.git main
```
- With HTTP, by running:
```shell
git push --set-upstream https://gitlab.example.com/namespace/myproject.git master
```
In the commands above:
- Replace `gitlab.example.com` with the machine domain name hosts your Git repository.
- Replace `namespace` with your [namespace](../namespace/index.md) name.
- Replace `myproject` with your project name.
- If specifying a port, change `00` to your project's required port number.
- Optional. To export existing repository tags, append the `--tags` flag to your `git push` command.
1. Optional. Configure the remote:
```shell
git remote add origin https://gitlab.example.com/namespace/myproject.git
```
When the push completes, GitLab displays the following message:
```shell
remote: The private project namespace/myproject was created.
```
To view your new project, go to `https://gitlab.example.com/namespace/myproject`.
By default, your project's visibility is set to **Private**,
but you can [change the project's visibility](../public_access.md#change-project-visibility).
## Related topics
- [Create a project with `git push`](../../topics/git/project.md)
- [Reserved project and group names](../../user/reserved_names.md)
- [Limitations on project and group names](../../user/reserved_names.md#limitations-on-usernames-project-and-group-names-and-slugs)
- [Manage projects](working_with_projects.md)

View File

@ -6,10 +6,6 @@ module API
helpers ::API::Helpers::PackagesHelpers
after_validation do
if Feature.disabled?(:packages_protected_packages, user_project)
render_api_error!("'packages_protected_packages' feature flag is disabled", :not_found)
end
authenticate!
authorize_admin_package!
end
@ -28,7 +24,6 @@ module API
]
tags %w[projects]
is_array true
hidden true
end
get do
present user_project.package_protection_rules, with: Entities::Projects::Packages::Protection::Rule
@ -44,7 +39,6 @@ module API
{ code: 422, message: 'Unprocessable Entity' }
]
tags %w[projects]
hidden true
end
params do
requires :package_name_pattern, type: String,
@ -80,7 +74,6 @@ module API
{ code: 422, message: 'Unprocessable Entity' }
]
tags %w[projects]
hidden true
end
params do
optional :package_name_pattern, type: String,
@ -113,7 +106,6 @@ module API
{ code: 404, message: 'Not Found' }
]
tags %w[projects]
hidden true
end
delete do
package_protection_rule = user_project.package_protection_rules.find(params[:package_protection_rule_id])

View File

@ -176,11 +176,15 @@ module API
produces ['application/yaml']
tags %w[usage_data metrics]
end
params do
optional :include_paths, type: Boolean, desc: 'Include file paths in the metric definitions',
documentation: { example: true, default: false }
end
get 'metric_definitions', urgency: :low do
content_type 'application/yaml'
env['api.format'] = :binary
Gitlab::Usage::MetricDefinition.dump_metrics_yaml
Gitlab::Usage::MetricDefinition.dump_metrics_yaml(include_paths: !!params[:include_paths])
end
end
end

View File

@ -172,8 +172,16 @@ module Gitlab
definitions[key_path]&.to_context
end
def dump_metrics_yaml
@metrics_yaml ||= definitions.values.map(&:to_h).map(&:deep_stringify_keys).to_yaml
def dump_metrics_yaml(include_paths:)
@metrics_yaml ||= {}
@metrics_yaml[include_paths.to_s] ||= begin
metrics = definitions.values.map do |definition|
result = definition.to_h
result[:file_path] = Pathname.new(definition.path).relative_path_from(Rails.root).to_s if include_paths
result
end
metrics.map(&:deep_stringify_keys).to_yaml
end
end
private

View File

@ -37,17 +37,23 @@ def write_metadata(file)
stage: none
group: none
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
noindex: false
---
# Breaking change windows
# Breaking change deployments on GitLab.com
Changes are deployed continuously to GitLab.com. However, breaking changes
can require more time to prepare for.
In the month before the GitLab 18.0 release, breaking changes will be deployed
during three time windows. The following tables list when each breaking change will be deployed.
<!--
Do not edit this page directly.
This page is generated by lib/tasks/gitlab/docs/compile_windows.rake and
from the yaml files in /data/deprecations.
To update this file, run: bin/rake gitlab:docs:compile_windows
-->
GitLab.com has breaking changes that will be deployed during the following windows.
METADATA
end

View File

@ -34856,9 +34856,6 @@ msgstr ""
msgid "MlModelRegistry|Edit model version"
msgstr ""
msgid "MlModelRegistry|Edit version"
msgstr ""
msgid "MlModelRegistry|Enter a model description"
msgstr ""

View File

@ -118,7 +118,6 @@ ee/spec/frontend/saml_providers/saml_settings_form_spec.js
ee/spec/frontend/security_configuration/components/app_spec.js
ee/spec/frontend/security_configuration/components/dynamic_fields_spec.js
ee/spec/frontend/security_configuration/components/expandable_section_spec.js
ee/spec/frontend/security_configuration/dast_pre_scan_verification/components/pre_scan_verification_configurator_spec.js
ee/spec/frontend/security_configuration/dast_profiles/components/dast_profiles_list_spec.js
ee/spec/frontend/security_configuration/dast_profiles/dast_scanner_profiles_form/components/dast_scanner_profiles_form_spec.js
ee/spec/frontend/security_dashboard/components/project/security_scanner_alert_spec.js
@ -428,7 +427,6 @@ spec/frontend/tooltips/components/tooltips_spec.js
spec/frontend/tooltips/index_spec.js
spec/frontend/usage_quotas/storage/components/container_registry_usage_spec.js
spec/frontend/usage_quotas/storage/components/namespace_storage_app_spec.js
spec/frontend/users/profile/actions/components/user_actions_app_spec.js
spec/frontend/users_select/index_spec.js
spec/frontend/vue_alerts_spec.js
spec/frontend/vue_merge_request_widget/components/checks/conflicts_spec.js

View File

@ -0,0 +1,47 @@
import ModelVersionEdit from '~/ml/model_registry/components/model_version_edit.vue';
import EditMlModelVersion from '~/ml/model_registry/apps/edit_ml_model_version.vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
describe('ml/model_registry/apps/edit_ml_model.vue', () => {
let wrapper;
const mountComponent = (canWriteModelRegistry) => {
wrapper = shallowMountExtended(EditMlModelVersion, {
propsData: {
projectPath: 'project/path',
canWriteModelRegistry,
markdownPreviewPath: 'markdown/preview/path',
modelVersionPath: 'model/version/path',
modelGid: 'gid://gitlab/Ml::Model/1',
modelVersionVersion: '1.0.0',
modelVersionDescription: 'No desc',
},
});
};
const findModelVersionEdit = () => wrapper.findComponent(ModelVersionEdit);
it('when user has no permission does not render the model edit component', () => {
mountComponent(false);
expect(findModelVersionEdit().exists()).toBe(false);
});
it('when user has permission renders the model edit component', () => {
mountComponent(true);
expect(findModelVersionEdit().props()).toEqual({
projectPath: 'project/path',
disableAttachments: false,
modelWithVersion: {
id: 'gid://gitlab/Ml::Model/1',
version: {
version: '1.0.0',
description: 'No desc',
},
},
modelVersionPath: 'model/version/path',
markdownPreviewPath: 'markdown/preview/path',
});
});
});

View File

@ -8,7 +8,6 @@ import { createAlert } from '~/alert';
import { ShowMlModelVersion } from '~/ml/model_registry/apps';
import ModelVersionDetail from '~/ml/model_registry/components/model_version_detail.vue';
import ModelVersionActionsDropdown from '~/ml/model_registry/components/model_version_actions_dropdown.vue';
import ModelVersionEdit from '~/ml/model_registry/components/model_version_edit.vue';
import deleteModelVersionMutation from '~/ml/model_registry/graphql/mutations/delete_model_version.mutation.graphql';
import TitleArea from '~/vue_shared/components/registry/title_area.vue';
import LoadOrErrorOrShow from '~/ml/model_registry/components/load_or_error_or_show.vue';
@ -43,11 +42,11 @@ describe('ml/model_registry/apps/show_model_version.vue', () => {
apolloProvider = null;
});
const createWrapper = (
const createWrapper = ({
resolver = jest.fn().mockResolvedValue(modelVersionQueryWithAuthor),
deleteResolver = jest.fn().mockResolvedValue(deleteModelVersionResponses.success),
canWriteModelRegistry = true,
) => {
} = {}) => {
const requestHandlers = [
[getModelVersionQuery, resolver],
[deleteModelVersionMutation, deleteResolver],
@ -61,6 +60,7 @@ describe('ml/model_registry/apps/show_model_version.vue', () => {
modelId: 1,
modelVersionId: 2,
projectPath: 'path/to/project',
editModelVersionPath: 'edit/model/version/path',
canWriteModelRegistry,
importPath: 'path/to/import',
modelPath: 'path/to/model',
@ -81,9 +81,9 @@ describe('ml/model_registry/apps/show_model_version.vue', () => {
const findModelVersionDetail = () => wrapper.findComponent(ModelVersionDetail);
const findModelVersionActionsDropdown = () => wrapper.findComponent(ModelVersionActionsDropdown);
const findLoadOrErrorOrShow = () => wrapper.findComponent(LoadOrErrorOrShow);
const findEditButton = () => wrapper.findComponent(ModelVersionEdit);
const findModelMetadata = () => wrapper.findByTestId('metadata');
const findTimeAgoTooltip = () => wrapper.findComponent(TimeAgoTooltip);
const findModelVersionEditButton = () => wrapper.findByTestId('edit-model-version-button');
it('renders the title', () => {
createWrapper();
@ -91,10 +91,28 @@ describe('ml/model_registry/apps/show_model_version.vue', () => {
expect(findTitleArea().props('title')).toBe('blah / 1.2.3');
});
describe('Model version edit button', () => {
beforeEach(() => createWrapper());
it('displays model version edit button', () => {
expect(findModelVersionEditButton().props()).toMatchObject({
variant: 'confirm',
category: 'primary',
});
});
describe('when user has no permission to write model registry', () => {
it('does not display model edit button', () => {
createWrapper({ canWriteModelRegistry: false });
expect(findModelVersionEditButton().exists()).toBe(false);
});
});
});
it('Requests data with the right parameters', async () => {
const resolver = jest.fn().mockResolvedValue(modelVersionQueryWithAuthor);
createWrapper(resolver);
createWrapper({ resolver });
await waitForPromises();
@ -133,7 +151,7 @@ describe('ml/model_registry/apps/show_model_version.vue', () => {
it('Shows error message on error', async () => {
const error = new Error('Failure!');
createWrapper(jest.fn().mockRejectedValue(error));
createWrapper({ resolver: jest.fn().mockRejectedValue(error) });
await waitForPromises();
@ -180,7 +198,7 @@ describe('ml/model_registry/apps/show_model_version.vue', () => {
it('Displays an alert upon failed delete mutation', async () => {
const failedDeleteResolver = jest.fn().mockResolvedValue(deleteModelVersionResponses.failure);
createWrapper(undefined, failedDeleteResolver);
createWrapper({ deleteResolver: failedDeleteResolver });
findModelVersionActionsDropdown().vm.$emit('delete-model-version');
@ -195,7 +213,7 @@ describe('ml/model_registry/apps/show_model_version.vue', () => {
it('Logs to sentry upon failed delete mutation', async () => {
const failedDeleteResolver = jest.fn().mockResolvedValue(deleteModelVersionResponses.failure);
createWrapper(undefined, failedDeleteResolver);
createWrapper({ deleteResolver: failedDeleteResolver });
findModelVersionActionsDropdown().vm.$emit('delete-model-version');
@ -208,16 +226,4 @@ describe('ml/model_registry/apps/show_model_version.vue', () => {
},
);
});
it('Does not display the edit button when user is not allowed to write', async () => {
createWrapper(undefined, undefined, false);
await waitForPromises();
expect(findEditButton().exists()).toBe(false);
});
it('Displays the edit button when user is allowed to write', async () => {
createWrapper(undefined, undefined, true);
await waitForPromises();
expect(findEditButton().exists()).toBe(true);
});
});

View File

@ -1,16 +1,12 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import { GlModal } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import * as Sentry from '~/sentry/sentry_browser_wrapper';
import { visitUrl } from '~/lib/utils/url_utility';
import ModelVersionEdit from '~/ml/model_registry/components/model_version_edit.vue';
import editModelVersionMutation from '~/ml/model_registry/graphql/mutations/edit_model_version.mutation.graphql';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { createMockDirective } from 'helpers/vue_mock_directive';
import MarkdownEditor from '~/vue_shared/components/markdown/markdown_editor.vue';
import { editModelVersionResponses, modelWithVersion } from '../graphql_mock_data';
@ -41,27 +37,24 @@ describe('ModelVersionEdit', () => {
apolloProvider = createMockApollo(requestHandlers);
wrapper = shallowMountExtended(ModelVersionEdit, {
propsData: { modelWithVersion: modelVersionProp, disableAttachments: true },
provide: {
propsData: {
modelWithVersion: modelVersionProp,
projectPath: 'some/project',
maxAllowedFileSize: 99999,
markdownPreviewPath: '/markdown-preview',
modelId: 'gid://gitlab/Ml::Model/1',
},
directives: {
GlModal: createMockDirective('gl-modal'),
modelVersionPath: 'model/version/path',
disableAttachments: true,
},
apolloProvider,
});
};
const findEditModal = () => wrapper.findComponent(ModelVersionEdit);
const findPrimaryButton = () => wrapper.findByTestId('primary-button');
const findSecondaryButton = () => wrapper.findByTestId('secondary-button');
const findModelDescription = () => wrapper.findByTestId('description-id');
const findMarkdownEditor = () => wrapper.findComponent(MarkdownEditor);
const findGlModal = () => wrapper.findComponent(GlModal);
const findGlAlert = () => wrapper.findByTestId('modal-edit-alert');
const findGlAlert = () => wrapper.findByTestId('edit-alert');
const submitForm = async () => {
findGlModal().vm.$emit('primary', new Event('primary'));
findPrimaryButton().vm.$emit('click');
await waitForPromises();
};
const findDescriptionGroup = () => wrapper.findByTestId('description-group-id');
@ -71,25 +64,20 @@ describe('ModelVersionEdit', () => {
createWrapper();
});
it('renders the component', () => {
expect(findEditModal().exists()).toBe(true);
});
it('pre-populates the model description input', () => {
expect(findModelDescription().attributes('value')).toBe(modelWithVersion.version.description);
});
it('renders the edit button in the modal', () => {
expect(findGlModal().props('actionPrimary')).toEqual({
attributes: { variant: 'confirm' },
text: 'Save changes',
expect(findPrimaryButton().props()).toMatchObject({
variant: 'confirm',
disabled: false,
});
});
it('renders the cancel button in the modal', () => {
expect(findGlModal().props('actionSecondary')).toEqual({
text: 'Cancel',
attributes: { variant: 'default' },
expect(findSecondaryButton().props()).toMatchObject({
variant: 'default',
});
});

View File

@ -235,7 +235,6 @@ describe('PackageTitle', () => {
describe('badge "protected"', () => {
const createComponentForBadgeProtected = async ({
packageEntityProtectionRuleExists = true,
glFeaturesPackagesProtectedPackages = true,
} = {}) => {
await createComponent(
{
@ -244,7 +243,6 @@ describe('PackageTitle', () => {
},
{
...defaultProvide,
glFeatures: { packagesProtectedPackages: glFeaturesPackagesProtectedPackages },
},
);
};
@ -269,13 +267,5 @@ describe('PackageTitle', () => {
expect(findProtectedBadge().exists()).toBe(false);
});
});
describe('when feature flag ":packages_protected_packages" is disabled', () => {
it('does not show badge', () => {
createComponentForBadgeProtected({ glFeaturesPackagesProtectedPackages: false });
expect(findProtectedBadge().exists()).toBe(false);
});
});
});
});

View File

@ -343,10 +343,7 @@ describe('packages_list_row', () => {
});
describe('badge "protected"', () => {
const mountComponentForBadgeProtected = ({
packageEntityProtectionRuleExists = true,
glFeaturesPackagesProtectedPackages = true,
} = {}) =>
const mountComponentForBadgeProtected = ({ packageEntityProtectionRuleExists = true } = {}) =>
mountComponent({
packageEntity: {
...packageWithoutTags,
@ -354,7 +351,6 @@ describe('packages_list_row', () => {
},
provide: {
...defaultProvide,
glFeatures: { packagesProtectedPackages: glFeaturesPackagesProtectedPackages },
},
});
@ -378,13 +374,5 @@ describe('packages_list_row', () => {
expect(findProtectedBadge().exists()).toBe(false);
});
});
describe('when feature flag ":packages_protected_packages" disabled', () => {
it('does not show badge', () => {
mountComponentForBadgeProtected({ glFeaturesPackagesProtectedPackages: false });
expect(findProtectedBadge().exists()).toBe(false);
});
});
});
});

View File

@ -37,7 +37,6 @@ describe('Registry Settings app', () => {
...(IS_EE && { showDependencyProxySettings: true }),
glFeatures: {
containerRegistryProtectedContainers: true,
packagesProtectedPackages: true,
},
isContainerRegistryMetadataDatabaseEnabled: false,
};
@ -139,21 +138,6 @@ describe('Registry Settings app', () => {
});
}
describe('when feature flag "packagesProtectedPackages" is disabled', () => {
it.each([true, false])(
'package protection rules settings is hidden if showPackageRegistrySettings is %s',
(showPackageRegistrySettings) => {
mountComponent({
...defaultProvide,
showPackageRegistrySettings,
glFeatures: { packagesProtectedPackages: false },
});
expect(findPackagesProtectionRules().exists()).toBe(false);
},
);
});
describe('when feature flag "containerRegistryProtectedContainers" is disabled', () => {
it.each([true, false])(
'container protection rules settings is hidden if showContainerRegistrySettings is %s',
@ -164,7 +148,7 @@ describe('Registry Settings app', () => {
glFeatures: { containerRegistryProtectedContainers: false },
});
expect(findPackagesProtectionRules().exists()).toBe(false);
expect(findContainerProtectionRules().exists()).toBe(false);
},
);
});

View File

@ -55,7 +55,7 @@ describe('User Actions App', () => {
it('shows copy user id action', () => {
createWrapper();
expect(findAction().text()).toBe(`Copy user ID: ${USER_ID}`);
expect(findAction().findComponent('button').attributes('data-clipboard-text')).toBe(USER_ID);
expect(findAction().find('button').attributes('data-clipboard-text')).toBe(USER_ID);
});
it('shows subscription link when subscription url was presented', () => {

View File

@ -190,9 +190,36 @@ RSpec.describe Projects::Ml::ModelRegistryHelper, feature_category: :mlops do
'maxAllowedFileSize' => 10737418240,
"importPath" => "/api/v4/projects/#{project.id}/packages/ml_models/#{model_version.id}/files/",
"modelPath" => "/#{project.full_path}/-/ml/models/1",
"editModelVersionPath" => "/#{project.full_path}/-/ml/models/1/versions/#{model_version.id}/edit",
"markdownPreviewPath" => "/#{project.full_path}/-/preview_markdown"
})
end
end
describe '#edit_ml_model_version_data' do
let_it_be(:model) do
build_stubbed(:ml_models, :with_latest_version_and_package, project: project, id: 1)
end
let_it_be(:model_version) do
model.latest_version
end
subject(:parsed) { Gitlab::Json.parse(helper.edit_ml_model_version_data(model_version, user)) }
it 'generates the correct data' do
stub_member_access_level(project, owner: user)
is_expected.to eq({
"projectPath" => project.full_path,
"canWriteModelRegistry" => true,
"markdownPreviewPath" => "/#{project.full_path}/-/preview_markdown",
"modelVersionPath" => "/#{project.full_path}/-/ml/models/1/versions/#{model_version.id}",
"modelGid" => model.to_global_id.to_s,
"modelVersionDescription" => model_version.description,
"modelVersionVersion" => model_version.version
})
end
context 'when user does not have write access to model registry' do
before do

View File

@ -501,6 +501,7 @@ RSpec.describe Gitlab::Usage::MetricDefinition, feature_category: :service_ping
end
describe 'dump_metrics_yaml' do
let(:include_paths) { false }
let(:other_attributes) do
{
description: 'Test metric definition',
@ -529,6 +530,9 @@ RSpec.describe Gitlab::Usage::MetricDefinition, feature_category: :service_ping
File.join(metric2, '**', '*.yml')
]
)
write_metric(metric1, path, yaml_content)
write_metric(metric2, other_path, other_yaml_content)
end
after do
@ -536,13 +540,31 @@ RSpec.describe Gitlab::Usage::MetricDefinition, feature_category: :service_ping
FileUtils.rm_rf(metric2)
end
subject { described_class.dump_metrics_yaml }
subject { described_class.dump_metrics_yaml(include_paths: include_paths) }
it 'returns a YAML with both metrics in a sequence' do
write_metric(metric1, path, yaml_content)
write_metric(metric2, other_path, other_yaml_content)
is_expected.to eq([attributes, other_attributes].map(&:deep_stringify_keys).to_yaml)
end
context "with true include_paths" do
let(:include_paths) { true }
it 'returns a YAML including filepaths' do
metrics = YAML.safe_load(subject)
added_attribute = ['file_path']
# First metric
serialized_metric = metrics[0]
expect(serialized_metric).to include(attributes.deep_stringify_keys)
expect(serialized_metric.keys - attributes.keys.map(&:to_s)).to eq added_attribute
expect(serialized_metric['file_path']).to end_with(path)
# Second metric
serialized_metric = metrics[1]
expect(serialized_metric).to include(other_attributes.deep_stringify_keys)
expect(serialized_metric.keys - other_attributes.keys.map(&:to_s)).to eq added_attribute
expect(serialized_metric['file_path']).to end_with(other_path)
end
end
end
end

View File

@ -160,16 +160,4 @@ RSpec.describe 'Creating the packages protection rule', :aggregate_failures, fea
end
end
end
context "when feature flag ':packages_protected_packages' disabled" do
before do
stub_feature_flags(packages_protected_packages: false)
end
it_behaves_like 'an erroneous response'
it 'returns error of disabled feature flag' do
subject.tap { expect_graphql_errors_to_include(/'packages_protected_packages' feature flag is disabled/) }
end
end
end

View File

@ -75,14 +75,4 @@ RSpec.describe 'Deleting a package protection rule', :aggregate_failures, featur
it { subject.tap { expect_graphql_errors_to_include(/you don't have permission to perform this action/) } }
end
end
context "when feature flag ':packages_protected_packages' disabled" do
before do
stub_feature_flags(packages_protected_packages: false)
end
it_behaves_like 'an erroneous response'
it { subject.tap { expect_graphql_errors_to_include(/'packages_protected_packages' feature flag is disabled/) } }
end
end

View File

@ -119,16 +119,4 @@ RSpec.describe 'Updating the packages protection rule', :aggregate_failures, fea
it { is_expected.tap { expect_graphql_errors_to_include(/you don't have permission to perform this action/) } }
end
end
context "when feature flag ':packages_protected_packages' disabled" do
before do
stub_feature_flags(packages_protected_packages: false)
end
it_behaves_like 'an erroneous response'
it 'returns error of disabled feature flag' do
is_expected.tap { expect_graphql_errors_to_include(/'packages_protected_packages' feature flag is disabled/) }
end
end
end

View File

@ -65,20 +65,4 @@ RSpec.describe 'getting the packages protection rules linked to a project', :agg
expect(graphql_data_at(:project, :packagesProtectionRules, :nodes)).to eq []
end
end
context "when feature flag ':packages_protected_packages' disabled" do
let_it_be(:package_protection_rule) { create(:package_protection_rule, project: project) }
before do
stub_feature_flags(packages_protected_packages: false)
subject
end
it_behaves_like 'a working graphql query'
it 'returns no package protection rules' do
expect(graphql_data_at(:project, :packagesProtectionRules, :nodes)).to eq []
end
end
end

View File

@ -107,23 +107,5 @@ RSpec.describe 'getting a package list for a project', feature_category: :packag
end
end
end
context "when feature flag ':packages_protected_packages' disabled" do
before_all do
resource.add_maintainer(current_user)
end
before do
stub_feature_flags(packages_protected_packages: false)
post_graphql(query, current_user: current_user)
end
it 'returns false for the field protectionRuleExists for each package' do
graphql_data_at(resource_type, :packages, :nodes).each do |package|
expect(package['protectionRuleExists']).to eq false
end
end
end
end
end

View File

@ -26,14 +26,6 @@ RSpec.describe API::ProjectPackagesProtectionRules, :aggregate_failures, feature
end
shared_examples 'rejecting project packages protection rules request when enough permissions' do
context 'when feature flag is disabled' do
before do
stub_feature_flags(packages_protected_packages: false)
end
it_behaves_like 'returning response status', :not_found
end
it_behaves_like 'rejecting protection rules request when invalid project'
end

View File

@ -442,20 +442,67 @@ RSpec.describe API::UsageData, feature_category: :service_ping do
describe 'GET /usage_data/metric_definitions' do
let(:endpoint) { '/usage_data/metric_definitions' }
let(:metric_yaml) do
{ 'key_path' => 'counter.category.event', 'description' => 'Metric description' }.to_yaml
let(:include_paths) { false }
let(:metrics) do
{
'counter.category.event' => metric1,
'counter.category.event2' => metric2
}
end
let(:metric1_attributes) do
{ 'key_path' => 'counter.category.event', 'description' => 'Metric description' }
end
let(:metric2_attributes) do
{ 'key_path' => 'counter.category.event2', 'description' => 'Metric description2' }
end
let(:metric1) { Gitlab::Usage::MetricDefinition.new('/metrics/test_metric1.yml', metric1_attributes.dup) }
let(:metric2) { Gitlab::Usage::MetricDefinition.new('/metrics/test_metric2.yml', metric2_attributes.dup) }
let(:metric_yaml) { [metric1_attributes, metric2_attributes].to_yaml }
before do
allow(Gitlab::Usage::MetricDefinition).to receive(:definitions).and_return(metrics)
end
around do |example|
Gitlab::Usage::MetricDefinition.instance_variable_set(:@metrics_yaml, nil)
example.run
Gitlab::Usage::MetricDefinition.instance_variable_set(:@metrics_yaml, nil)
end
context 'without authentication' do
it 'returns a YAML file', :aggregate_failures do
allow(Gitlab::Usage::MetricDefinition).to receive(:dump_metrics_yaml).and_return(metric_yaml)
get api(endpoint)
get(api(endpoint), params: { include_paths: include_paths })
expect(response).to have_gitlab_http_status(:ok)
expect(response.media_type).to eq('application/yaml')
expect(response.body).to eq(metric_yaml)
end
end
context "without include_paths passed" do
it 'uses false include_paths by default', :aggregate_failures do
get(api(endpoint))
expect(response.body).to eq(metric_yaml)
end
end
context "with include_paths being true" do
let(:include_paths) { true }
it 'passes include_paths value', :aggregate_failures do
get(api(endpoint), params: { include_paths: include_paths })
payload = YAML.safe_load(response.body)
expect(payload.length).to be 2
expect(payload[0]).to include(metric1_attributes)
expect(payload[0]['file_path']).to end_with('metrics/test_metric1.yml')
expect(payload[1]).to include(metric2_attributes)
expect(payload[1]['file_path']).to end_with('metrics/test_metric2.yml')
end
end
end
end

View File

@ -6,20 +6,6 @@ RSpec.describe Groups::PackagesController, feature_category: :package_registry d
let_it_be(:group) { create(:group, :public) }
let_it_be(:project) { create(:project, :public, group: group) }
shared_examples 'having the feature flag "packagesProtectedPackages"' do
it { is_expected.to have_gitlab_http_status(:ok) }
it { is_expected.to have_attributes(body: have_pushed_frontend_feature_flags(packagesProtectedPackages: true)) }
context 'when feature flag "packages_protected_packages" is disabled' do
before do
stub_feature_flags(packages_protected_packages: false)
end
it { is_expected.to have_gitlab_http_status(:ok) }
it { is_expected.to have_attributes(body: have_pushed_frontend_feature_flags(packagesProtectedPackages: false)) }
end
end
describe 'GET #index' do
subject do
get group_packages_path(group_id: group.full_path)
@ -27,8 +13,6 @@ RSpec.describe Groups::PackagesController, feature_category: :package_registry d
end
it { is_expected.to have_gitlab_http_status(:ok) }
it_behaves_like 'having the feature flag "packagesProtectedPackages"'
end
describe 'GET #show' do
@ -40,7 +24,5 @@ RSpec.describe Groups::PackagesController, feature_category: :package_registry d
end
it { is_expected.to have_gitlab_http_status(:ok) }
it_behaves_like 'having the feature flag "packagesProtectedPackages"'
end
end

View File

@ -9,13 +9,17 @@ RSpec.describe Projects::Ml::ModelVersionsController, feature_category: :mlops d
let_it_be(:model) { create(:ml_models, :with_versions, project: project) }
let_it_be(:version) { model.versions.first }
let(:model_registry_enabled) { true }
let(:read_model_registry) { true }
let(:write_model_registry) { true }
before do
allow(Ability).to receive(:allowed?).and_call_original
allow(Ability).to receive(:allowed?)
.with(user, :read_model_registry, project)
.and_return(model_registry_enabled)
.and_return(read_model_registry)
allow(Ability).to receive(:allowed?)
.with(user, :write_model_registry, project)
.and_return(write_model_registry)
sign_in(user)
end
@ -58,7 +62,57 @@ RSpec.describe Projects::Ml::ModelVersionsController, feature_category: :mlops d
end
context 'when user does not have access' do
let(:model_registry_enabled) { false }
let(:read_model_registry) { false }
it { is_expected.to have_gitlab_http_status(:not_found) }
end
end
describe 'edit' do
let(:model_id) { model.id }
let(:version_id) { version.id }
let(:request_project) { model.project }
subject(:edit_request) do
edit_model_version
response
end
before do
edit_request
end
it 'renders the template' do
is_expected.to render_template('projects/ml/model_versions/edit')
end
it 'fetches the correct model_version' do
edit_request
expect(assigns(:model)).to eq(model)
expect(assigns(:model_version)).to eq(version)
end
context 'when version id does not exist' do
let(:version_id) { non_existing_record_id }
it { is_expected.to have_gitlab_http_status(:not_found) }
end
context 'when version and model id are correct but project is not' do
let(:request_project) { another_project }
it { is_expected.to have_gitlab_http_status(:not_found) }
end
context 'when user does not have access' do
let(:read_model_registry) { false }
it { is_expected.to have_gitlab_http_status(:not_found) }
end
context 'when user does not have write access' do
let(:write_model_registry) { false }
it { is_expected.to have_gitlab_http_status(:not_found) }
end
@ -100,7 +154,13 @@ RSpec.describe Projects::Ml::ModelVersionsController, feature_category: :mlops d
end
context 'when user does not have access' do
let(:model_registry_enabled) { false }
let(:read_model_registry) { false }
it { is_expected.to have_gitlab_http_status(:not_found) }
end
context 'when user does not have write access' do
let(:write_model_registry) { false }
it { is_expected.to have_gitlab_http_status(:not_found) }
end
@ -112,6 +172,10 @@ RSpec.describe Projects::Ml::ModelVersionsController, feature_category: :mlops d
get project_ml_model_version_path(request_project, model_id, version_id)
end
def edit_model_version
get edit_project_ml_model_version_path(request_project, model_id, version_id)
end
def new_model_version
get new_project_ml_model_version_path(request_project, model_id)
end

View File

@ -5,24 +5,6 @@ require 'spec_helper'
RSpec.describe Projects::Packages::PackagesController, feature_category: :package_registry do
let_it_be(:project) { create(:project, :public) }
shared_examples 'having the feature flag "packagesProtectedPackages"' do
it 'pushes the feature flag to the view' do
is_expected.to have_gitlab_http_status(:ok)
is_expected.to have_attributes(body: have_pushed_frontend_feature_flags(packagesProtectedPackages: true))
end
context 'when feature flag "packages_protected_packages" is disabled' do
before do
stub_feature_flags(packages_protected_packages: false)
end
it 'does not pushes the feature flag to the view' do
is_expected.to have_gitlab_http_status(:ok)
is_expected.to have_attributes(body: have_pushed_frontend_feature_flags(packagesProtectedPackages: false))
end
end
end
describe 'GET #index' do
subject do
get namespace_project_packages_path(namespace_id: project.namespace, project_id: project)
@ -30,8 +12,6 @@ RSpec.describe Projects::Packages::PackagesController, feature_category: :packag
end
it { is_expected.to have_gitlab_http_status(:ok) }
it_behaves_like 'having the feature flag "packagesProtectedPackages"'
end
describe 'GET #show' do
@ -43,7 +23,5 @@ RSpec.describe Projects::Packages::PackagesController, feature_category: :packag
end
it { is_expected.to have_gitlab_http_status(:ok) }
it_behaves_like 'having the feature flag "packagesProtectedPackages"'
end
end

View File

@ -49,7 +49,6 @@ RSpec.describe Projects::Settings::PackagesAndRegistriesController, feature_cate
allow(ContainerRegistry::GitlabApiClient).to receive(:supports_gitlab_api?).and_return(true)
end
it_behaves_like 'pushed feature flag', :packages_protected_packages
it_behaves_like 'pushed feature flag', :packages_protected_packages_pypi
it_behaves_like 'pushed feature flag', :container_registry_protected_containers
end

View File

@ -370,38 +370,6 @@ RSpec.describe Packages::Npm::CreatePackageService, feature_category: :package_r
end
end
context 'when feature flag :packages_protected_packages disabled' do
let_it_be_with_reload(:package_protection_rule) do
create(:package_protection_rule, package_type: :npm, project: project)
end
before do
stub_feature_flags(packages_protected_packages: false)
end
context 'with matching package protection rule for all roles' do
using RSpec::Parameterized::TableSyntax
let(:package_name_pattern_no_match) { "#{package_name}_no_match" }
where(:package_name_pattern, :minimum_access_level_for_push) do
ref(:package_name) | :maintainer
ref(:package_name) | :owner
ref(:package_name_pattern_no_match) | :maintainer
ref(:package_name_pattern_no_match) | :owner
end
with_them do
before do
package_protection_rule.update!(package_name_pattern: package_name_pattern,
minimum_access_level_for_push: minimum_access_level_for_push)
end
it_behaves_like 'valid package'
end
end
end
context 'with package protection rule for different roles and package_name_patterns', :enable_admin_mode do
using RSpec::Parameterized::TableSyntax

View File

@ -292,3 +292,19 @@ mapping:
- '(?<prefix>ee/)?lib/api/(?<rest>.+hook.+)\.rb'
test:
- '{ee/,}spec/requests/api/**/*hook*_spec.rb'
# Registration/Onboarding
- source: 'ee/app/(controllers|services)/registrations/.*'
test: 'ee/spec/features/registrations/saas/*_spec.rb'
# ultimate trials
- source: 'ee/app/controllers/gitlab_subscriptions/trials_controller\.rb'
test: 'ee/spec/features/gitlab_subscriptions/trials/creation_*_spec.rb'
# duo pro trials
- source: 'ee/app/controllers/gitlab_subscriptions/trials/duo_pro_controller\.rb'
test: 'ee/spec/features/gitlab_subscriptions/trials/duo_pro/*_spec.rb'
# duo enterprise trials
- source: 'ee/app/controllers/gitlab_subscriptions/trials/duo_enterprise_controller\.rb'
test: 'ee/spec/features/gitlab_subscriptions/trials/duo_enterprise/*_spec.rb'