Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
93bb7ebeab
commit
cae885f7a8
|
|
@ -1 +1 @@
|
|||
64d528040625ca4350ce1d0f1df4f037f0cc5d37
|
||||
b1dfcadfaf2771f7a966b9eae97478c5fc8d7d9d
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
e2d561ff32972e193d836ea34c34a2f45a2b312c
|
||||
a92cf38ec9c34a3ccb4d8c07acadc3935fd250ef
|
||||
|
|
|
|||
2
Gemfile
2
Gemfile
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"},
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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"},
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -13,8 +13,7 @@ export default {
|
|||
},
|
||||
canWriteModelRegistry: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
required: true,
|
||||
},
|
||||
markdownPreviewPath: {
|
||||
type: String,
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -20,8 +20,7 @@ export default {
|
|||
},
|
||||
canWriteModelRegistry: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
required: true,
|
||||
},
|
||||
maxAllowedFileSize: {
|
||||
type: Number,
|
||||
|
|
|
|||
|
|
@ -20,8 +20,7 @@ export default {
|
|||
},
|
||||
canWriteModelRegistry: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
required: true,
|
||||
},
|
||||
maxAllowedFileSize: {
|
||||
type: Number,
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
showProtectedPackagesSettings() {
|
||||
return this.showPackageRegistrySettings && this.glFeatures.packagesProtectedPackages;
|
||||
return this.showPackageRegistrySettings;
|
||||
},
|
||||
showProtectedContainersSettings() {
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -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() });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 });
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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|
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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) } }
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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])
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -34856,9 +34856,6 @@ msgstr ""
|
|||
msgid "MlModelRegistry|Edit model version"
|
||||
msgstr ""
|
||||
|
||||
msgid "MlModelRegistry|Edit version"
|
||||
msgstr ""
|
||||
|
||||
msgid "MlModelRegistry|Enter a model description"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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', () => {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
16
tests.yml
16
tests.yml
|
|
@ -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'
|
||||
|
|
|
|||
Loading…
Reference in New Issue