Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2023-07-12 21:08:10 +00:00
parent 31f59b55c6
commit a6b21afb09
84 changed files with 1126 additions and 682 deletions

View File

@ -72,8 +72,6 @@ Performance/RegexpMatch:
- 'qa/qa/service/cluster_provider/k3d.rb'
- 'qa/qa/specs/spec_helper.rb'
- 'qa/qa/tools/ci/ff_changes.rb'
- 'rubocop/cop/project_path_helper.rb'
- 'rubocop/cop/qa/selector_usage.rb'
- 'scripts/changed-feature-flags'
- 'scripts/failed_tests.rb'
- 'scripts/lib/glfm/parse_examples.rb'
@ -83,14 +81,3 @@ Performance/RegexpMatch:
- 'scripts/qa/testcases-check'
- 'scripts/trigger-build.rb'
- 'sidekiq_cluster/cli.rb'
- 'spec/lib/gitlab/cluster/mixins/puma_cluster_spec.rb'
- 'spec/mailers/emails/in_product_marketing_spec.rb'
- 'spec/spec_helper.rb'
- 'spec/support/capybara.rb'
- 'spec/support/helpers/test_env.rb'
- 'spec/support/shared_contexts/features/integrations/integrations_shared_context.rb'
- 'spec/support/shared_examples/features/discussion_comments_shared_example.rb'
- 'spec/tooling/quality/test_level_spec.rb'
- 'tooling/danger/analytics_instrumentation.rb'
- 'tooling/danger/database_dictionary.rb'
- 'tooling/danger/specs/feature_category_suggestion.rb'

View File

@ -18,10 +18,10 @@ const axiosGet = (url, query, options, callback) => {
...options,
},
})
.then(({ data }) => {
.then(({ data, headers }) => {
callback(data);
return data;
return { data, headers };
});
};

View File

@ -53,7 +53,7 @@ export default {
});
},
[types.RECEIVE_SEARCHED_ITEMS_SUCCESS](state, results) {
const rawItems = results.data ? results.data : results; // Api.groups returns array, Api.projects returns object
const rawItems = results.data;
Object.assign(state, {
items: rawItems.map((rawItem) => ({
id: rawItem.id,

View File

@ -3,6 +3,7 @@ import { GlAvatarLabeled, GlCollapsibleListbox } from '@gitlab/ui';
import { debounce } from 'lodash';
import { s__ } from '~/locale';
import { getGroups, getDescendentGroups } from '~/rest_api';
import { normalizeHeaders, parseIntPagination } from '~/lib/utils/common_utils';
import { SEARCH_DELAY, GROUP_FILTERS } from '../constants';
export default {
@ -39,6 +40,8 @@ export default {
isFetching: false,
groups: [],
searchTerm: '',
pagination: {},
infiniteScrollLoading: false,
};
},
computed: {
@ -48,24 +51,29 @@ export default {
isFetchResultEmpty() {
return this.groups.length === 0;
},
infiniteScroll() {
return Boolean(this.pagination.nextPage);
},
},
mounted() {
this.retrieveGroups();
},
methods: {
retrieveGroups: debounce(function debouncedRetrieveGroups() {
retrieveGroups: debounce(async function debouncedRetrieveGroups() {
this.isFetching = true;
return this.fetchGroups()
.then((response) => {
this.groups = this.processGroups(response);
this.isFetching = false;
})
.catch(() => {
this.isFetching = false;
});
try {
const response = await this.fetchGroups();
this.pagination = this.processPagination(response);
this.groups = this.processGroups(response);
} catch {
this.onApiError();
} finally {
this.isFetching = false;
}
}, SEARCH_DELAY),
processGroups(response) {
const rawGroups = response.map((group) => ({
processGroups({ data }) {
const rawGroups = data.map((group) => ({
// `value` is needed for `GlCollapsibleListbox`
value: group.id,
id: group.id,
@ -76,6 +84,9 @@ export default {
return this.filterOutInvalidGroups(rawGroups);
},
processPagination({ headers }) {
return parseIntPagination(normalizeHeaders(headers));
},
filterOutInvalidGroups(groups) {
return groups.filter((group) => this.invalidGroups.indexOf(group.id) === -1);
},
@ -86,23 +97,43 @@ export default {
this.searchTerm = searchTerm;
this.retrieveGroups();
},
fetchGroups() {
fetchGroups(options = {}) {
const combinedOptions = {
...this.$options.defaultFetchOptions,
...options,
};
switch (this.groupsFilter) {
case GROUP_FILTERS.DESCENDANT_GROUPS:
return getDescendentGroups(
this.parentGroupId,
this.searchTerm,
this.$options.defaultFetchOptions,
);
return getDescendentGroups(this.parentGroupId, this.searchTerm, combinedOptions);
default:
return getGroups(this.searchTerm, this.$options.defaultFetchOptions);
return getGroups(this.searchTerm, combinedOptions);
}
},
async onBottomReached() {
this.infiniteScrollLoading = true;
try {
const response = await this.fetchGroups({ page: this.pagination.page + 1 });
this.pagination = this.processPagination(response);
this.groups.push(...this.processGroups(response));
} catch {
this.onApiError();
} finally {
this.infiniteScrollLoading = false;
}
},
onApiError() {
this.$emit('error', this.$options.i18n.errorMessage);
},
},
i18n: {
dropdownText: s__('GroupSelect|Select a group'),
searchPlaceholder: s__('GroupSelect|Search groups'),
emptySearchResult: s__('GroupSelect|No matching results'),
errorMessage: s__(
'GroupSelect|An error occurred fetching the groups. Please refresh the page to try again.',
),
},
defaultFetchOptions: {
exclude_internal: true,
@ -125,6 +156,10 @@ export default {
is-check-centered
:searching="isFetching"
:no-results-text="$options.i18n.emptySearchResult"
:infinite-scroll="infiniteScroll"
:infinite-scroll-loading="infiniteScrollLoading"
:total-items="pagination.total"
@bottom-reached="onBottomReached"
@select="onSelect"
@search="onSearch"
>

View File

@ -1,4 +1,6 @@
<script>
import * as Sentry from '@sentry/browser';
import { GlAlert } from '@gitlab/ui';
import { uniqueId } from 'lodash';
import Api from '~/api';
import { BV_SHOW_MODAL, BV_HIDE_MODAL } from '~/lib/utils/constants';
@ -19,6 +21,7 @@ export default {
GroupSelect,
InviteModalBase,
InviteGroupNotification,
GlAlert,
},
props: {
id: {
@ -83,6 +86,7 @@ export default {
isLoading: false,
modalId: uniqueId('invite-groups-modal-'),
groupToBeSharedWith: {},
groupSelectError: '',
};
},
computed: {
@ -165,6 +169,10 @@ export default {
clearValidation() {
this.invalidFeedbackMessage = '';
},
onGroupSelectError(error) {
this.groupSelectError = error;
Sentry.captureException(error);
},
},
labels: GROUP_MODAL_LABELS,
};
@ -197,6 +205,9 @@ export default {
:notification-link="$options.labels[inviteTo].notificationLink"
class="gl-mb-5"
/>
<gl-alert v-if="groupSelectError" class="gl-mb-5" variant="danger" :dismissible="false">{{
groupSelectError
}}</gl-alert>
</template>
<template #select>
@ -206,6 +217,7 @@ export default {
:parent-group-id="groupSelectParentId"
:invalid-groups="invalidGroups"
@input="clearValidation"
@error="onGroupSelectError"
/>
</template>
</invite-modal-base>

View File

@ -1,6 +1,5 @@
<script>
import { GlAlert } from '@gitlab/ui';
import ConvertDescriptionModal from 'ee_component/issues/show/components/convert_description_modal.vue';
import { getDraft, updateDraft, getLockVersion, clearDraft } from '~/lib/utils/autosave';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import { TYPENAME_ISSUE, TYPENAME_USER } from '~/graphql_shared/constants';
@ -16,7 +15,6 @@ import LockedWarning from './locked_warning.vue';
export default {
components: {
ConvertDescriptionModal,
DescriptionField,
DescriptionTemplateField,
EditActions,
@ -175,9 +173,6 @@ export default {
updateDraft(this.descriptionAutosaveKey, description, this.formState.lock_version);
}
},
setDescription(desc) {
this.formData.description = desc;
},
},
};
</script>
@ -219,14 +214,6 @@ export default {
:project-namespace="projectNamespace"
/>
</div>
<convert-description-modal
v-if="issueId && glFeatures.generateDescriptionAi"
class="gl-pl-5 gl-md-pl-0"
:resource-id="resourceId"
:user-id="userId"
@contentGenerated="setDescription"
/>
</div>
<description-field

View File

@ -1,5 +1,5 @@
import { initForm } from 'ee_else_ce/issues';
import { mountMarkdownEditor } from '~/vue_shared/components/markdown/mount_markdown_editor';
import { mountMarkdownEditor } from 'ee_else_ce/vue_shared/components/markdown/mount_markdown_editor';
import IssuableTemplateSelectors from '~/issuable/issuable_template_selectors';
initForm();

View File

@ -49,6 +49,9 @@ export default {
iconName() {
return this.isExpanded ? 'chevron-down' : 'chevron-right';
},
popoverId() {
return `popover-${this.pipelineIid}`;
},
},
watch: {
failedJobsCount(val) {
@ -77,8 +80,8 @@ export default {
<gl-button variant="link" @click="toggleWidget">
<gl-icon :name="iconName" />
{{ failedJobsCountText }}
<gl-icon id="target" name="information-o" />
<gl-popover target="target" placement="top">
<gl-icon :id="popoverId" name="information-o" />
<gl-popover :target="popoverId" placement="top">
<template #title> {{ $options.i18n.additionalInfoTitle }} </template>
<slot>
<gl-sprintf :message="$options.i18n.additionalInfoPopover">

View File

@ -1,10 +1,5 @@
<script>
import {
GlDropdown,
GlDropdownItem,
GlDropdownSectionHeader,
GlTooltipDirective,
} from '@gitlab/ui';
import { GlDisclosureDropdown, GlTooltipDirective } from '@gitlab/ui';
import { __ } from '~/locale';
export const i18n = {
@ -18,9 +13,7 @@ export default {
GlTooltip: GlTooltipDirective,
},
components: {
GlDropdown,
GlDropdownItem,
GlDropdownSectionHeader,
GlDisclosureDropdown,
},
inject: {
artifactsEndpoint: {
@ -42,6 +35,21 @@ export default {
},
},
computed: {
items() {
return [
{
name: this.$options.i18n.artifactSectionHeader,
items: this.artifacts.map(({ name, path }) => ({
text: name,
href: path,
extraAttrs: {
download: '',
rel: 'nofollow',
},
})),
},
];
},
shouldShowDropdown() {
return this.artifacts?.length;
},
@ -49,31 +57,16 @@ export default {
};
</script>
<template>
<gl-dropdown
<gl-disclosure-dropdown
v-if="shouldShowDropdown"
v-gl-tooltip
class="build-artifacts js-pipeline-dropdown-download"
:title="$options.i18n.artifacts"
:text="$options.i18n.artifacts"
:toggle-text="$options.i18n.artifacts"
:aria-label="$options.i18n.artifacts"
icon="download"
right
lazy
placement="right"
text-sr-only
>
<gl-dropdown-section-header>{{
$options.i18n.artifactSectionHeader
}}</gl-dropdown-section-header>
<gl-dropdown-item
v-for="(artifact, i) in artifacts"
:key="i"
:href="artifact.path"
rel="nofollow"
download
class="gl-word-break-word"
>
{{ artifact.name }}
</gl-dropdown-item>
</gl-dropdown>
:items="items"
/>
</template>

View File

@ -54,7 +54,7 @@ export default {
:label-for="$options.labelId"
label-cols="3"
label-cols-lg="2"
label-class="gl-pb-0! gl-overflow-wrap-break"
label-class="gl-pb-0! gl-overflow-wrap-break work-item-field-label"
class="gl-align-items-center"
>
<gl-form-select
@ -63,7 +63,7 @@ export default {
:options="$options.states"
:disabled="disabled"
data-testid="work-item-state-select"
class="gl-w-auto hide-select-decoration gl-pl-4 gl-my-1"
class="gl-w-auto hide-select-decoration gl-pl-4 gl-my-1 work-item-field-value"
:class="{ 'gl-bg-transparent! gl-cursor-text!': disabled }"
@change="setState"
/>

View File

@ -114,7 +114,7 @@ export default {
:note-id="noteId"
:is-system-note="true"
>
<span ref="gfm-content" v-safe-html="actionTextHtml"></span>
<span ref="gfm-content" v-safe-html="actionTextHtml" class="gl-word-break-word"></span>
<template v-if="canSeeDescriptionVersion" #extra-controls>
&middot;
<gl-button

View File

@ -303,7 +303,7 @@ export default {
<div class="form-row gl-mb-5 work-item-assignees gl-relative gl-flex-nowrap">
<span
:id="assigneesTitleId"
class="gl-font-weight-bold gl-mt-2 col-lg-2 col-3 gl-pt-2 min-w-fit-content gl-overflow-wrap-break"
class="gl-font-weight-bold gl-mt-2 col-lg-2 col-3 gl-pt-2 min-w-fit-content gl-overflow-wrap-break work-item-field-label"
data-testid="assignees-title"
>{{ assigneeText }}</span
>
@ -313,11 +313,12 @@ export default {
:selected-tokens="localAssignees"
:container-class="containerClass"
:class="{ 'gl-hover-border-gray-200': canUpdate }"
menu-class="token-selector-menu-class"
:dropdown-items="dropdownItems"
:loading="isLoadingUsers && !isLoadingMore"
:view-only="!canUpdate"
:allow-clear-all="isEditing"
class="assignees-selector gl-flex-grow-1 gl-border gl-border-white gl-rounded-base col-9 gl-align-self-start gl-px-0! gl-mx-2"
class="assignees-selector gl-flex-grow-1 gl-border gl-border-white gl-rounded-base col-9 gl-align-self-start gl-px-0! gl-mx-2 work-item-field-value"
data-testid="work-item-assignees-input"
@input="handleAssigneesInput"
@text-input="debouncedSearchKeyUpdate"

View File

@ -96,7 +96,7 @@ export default {
</script>
<template>
<section>
<div class="work-item-attributes-wrapper">
<work-item-state
:work-item="workItem"
:work-item-parent-id="workItemParentId"
@ -176,5 +176,5 @@ export default {
:work-item-type="workItemType"
@error="$emit('error', $event)"
/>
</section>
</div>
</template>

View File

@ -94,7 +94,7 @@ export default {
</script>
<template>
<div class="gl-mb-5 gl-border-t gl-pt-5">
<div class="gl-mb-5">
<div class="gl-display-inline-flex gl-align-items-center gl-mb-3">
<label class="d-block col-form-label gl-mr-5">{{ __('Description') }}</label>
<gl-button

View File

@ -9,6 +9,7 @@ import {
GlButton,
GlTooltipDirective,
GlEmptyState,
GlIntersectionObserver,
} from '@gitlab/ui';
import noAccessSvg from '@gitlab/svgs/dist/illustrations/analytics/no-access.svg?raw';
import { s__ } from '~/locale';
@ -75,6 +76,7 @@ export default {
WorkItemNotes,
WorkItemDetailModal,
AbuseCategorySelector,
GlIntersectionObserver,
},
mixins: [glFeatureFlagMixin()],
inject: ['fullPath', 'reportAbusePath'],
@ -106,6 +108,7 @@ export default {
isReportDrawerOpen: false,
reportedUrl: '',
reportedUserId: 0,
isStickyHeaderShowing: false,
};
},
apollo: {
@ -253,6 +256,9 @@ export default {
'gl-pt-5': !this.updateError && !this.isModal,
};
},
showIntersectionObserver() {
return !this.isModal && this.workItemsMvc2Enabled;
},
},
mounted() {
if (this.modalWorkItemIid) {
@ -358,6 +364,15 @@ export default {
this.reportedUrl = reply.url || {};
this.reportedUserId = reply.author ? getIdFromGraphQLId(reply.author.id) : 0;
},
hideStickyHeader() {
this.isStickyHeaderShowing = false;
},
showStickyHeader() {
// only if scrolled under the work item's title
if (this.$refs?.title?.$el.offsetTop < window.pageYOffset) {
this.isStickyHeaderShowing = true;
}
},
},
WORK_ITEM_TYPE_VALUE_OBJECTIVE,
@ -462,67 +477,148 @@ export default {
@click="$emit('close')"
/>
</div>
<work-item-title
v-if="workItem.title"
:work-item-id="workItem.id"
:work-item-title="workItem.title"
:work-item-type="workItemType"
:work-item-parent-id="workItemParentId"
:can-update="canUpdate"
@error="updateError = $event"
/>
<work-item-created-updated :work-item-iid="workItemIid" />
<work-item-attributes-wrapper
:work-item="workItem"
:work-item-parent-id="workItemParentId"
@error="updateError = $event"
/>
<work-item-description
v-if="hasDescriptionWidget"
:work-item-id="workItem.id"
:work-item-iid="workItem.iid"
class="gl-pt-5"
@error="updateError = $event"
/>
<work-item-award-emoji
v-if="workItemAwardEmoji"
:work-item-id="workItem.id"
:work-item-fullpath="workItem.project.fullPath"
:award-emoji="workItemAwardEmoji.awardEmoji"
:work-item-iid="workItemIid"
@error="updateError = $event"
/>
<work-item-tree
v-if="workItemType === $options.WORK_ITEM_TYPE_VALUE_OBJECTIVE"
:work-item-type="workItemType"
:parent-work-item-type="workItem.workItemType.name"
:work-item-id="workItem.id"
:work-item-iid="workItemIid"
:children="children"
:can-update="canUpdate"
:confidential="workItem.confidential"
@show-modal="openInModal"
/>
<work-item-notes
v-if="workItemNotes"
:work-item-id="workItem.id"
:work-item-iid="workItem.iid"
:work-item-type="workItemType"
:is-modal="isModal"
:assignees="workItemAssignees && workItemAssignees.assignees.nodes"
:can-set-work-item-metadata="canAssignUnassignUser"
:report-abuse-path="reportAbusePath"
class="gl-pt-5"
@error="updateError = $event"
@has-notes="updateHasNotes"
@openReportAbuse="openReportAbuseDrawer"
/>
<gl-empty-state
v-if="error"
:title="$options.i18n.fetchErrorTitle"
:description="error"
:svg-path="noAccessSvgPath"
/>
<div>
<work-item-title
v-if="workItem.title"
ref="title"
:work-item-id="workItem.id"
:work-item-title="workItem.title"
:work-item-type="workItemType"
:work-item-parent-id="workItemParentId"
:can-update="canUpdate"
@error="updateError = $event"
/>
<work-item-created-updated :work-item-iid="workItemIid" />
</div>
<gl-intersection-observer
v-if="showIntersectionObserver"
@appear="hideStickyHeader"
@disappear="showStickyHeader"
>
<transition name="issuable-header-slide">
<div
v-if="isStickyHeaderShowing"
class="issue-sticky-header gl-fixed gl-bg-white gl-border-b gl-z-index-3 gl-py-2"
data-testid="work-item-sticky-header"
>
<div
class="gl-align-items-center gl-mx-auto gl-px-5 gl-display-flex gl-max-w-container-xl"
>
<span class="gl-text-truncate gl-font-weight-bold gl-pr-3 gl-mr-auto">
{{ workItem.title }}
</span>
<gl-loading-icon v-if="updateInProgress" class="gl-mr-3" />
<gl-badge
v-if="workItem.confidential"
v-gl-tooltip.bottom
:title="confidentialTooltip"
variant="warning"
icon="eye-slash"
class="gl-mr-3 gl-cursor-help"
>{{ __('Confidential') }}</gl-badge
>
<work-item-todos
v-if="showWorkItemCurrentUserTodos"
:work-item-id="workItem.id"
:work-item-iid="workItemIid"
:work-item-fullpath="workItem.project.fullPath"
:current-user-todos="currentUserTodos"
@error="updateError = $event"
/>
<work-item-actions
:work-item-id="workItem.id"
:subscribed-to-notifications="workItemNotificationsSubscribed"
:work-item-type="workItemType"
:work-item-type-id="workItemTypeId"
:can-delete="canDelete"
:can-update="canUpdate"
:is-confidential="workItem.confidential"
:is-parent-confidential="parentWorkItemConfidentiality"
:work-item-reference="workItem.reference"
:work-item-create-note-email="workItem.createNoteEmail"
:is-modal="isModal"
@deleteWorkItem="
$emit('deleteWorkItem', { workItemType, workItemId: workItem.id })
"
@toggleWorkItemConfidentiality="toggleConfidentiality"
@error="updateError = $event"
/>
</div>
</div>
</transition>
</gl-intersection-observer>
<div
data-testid="work-item-overview"
:class="{ 'work-item-overview': workItemsMvc2Enabled }"
>
<section>
<work-item-attributes-wrapper
:class="{ 'gl-md-display-none!': workItemsMvc2Enabled }"
class="gl-border-b"
:work-item="workItem"
:work-item-parent-id="workItemParentId"
@error="updateError = $event"
/>
<work-item-description
v-if="hasDescriptionWidget"
:work-item-id="workItem.id"
:work-item-iid="workItem.iid"
class="gl-pt-5"
@error="updateError = $event"
/>
<work-item-award-emoji
v-if="workItemAwardEmoji"
:work-item-id="workItem.id"
:work-item-fullpath="workItem.project.fullPath"
:award-emoji="workItemAwardEmoji.awardEmoji"
:work-item-iid="workItemIid"
@error="updateError = $event"
/>
<work-item-tree
v-if="workItemType === $options.WORK_ITEM_TYPE_VALUE_OBJECTIVE"
:work-item-type="workItemType"
:parent-work-item-type="workItem.workItemType.name"
:work-item-id="workItem.id"
:work-item-iid="workItemIid"
:children="children"
:can-update="canUpdate"
:confidential="workItem.confidential"
@show-modal="openInModal"
/>
<work-item-notes
v-if="workItemNotes"
:work-item-id="workItem.id"
:work-item-iid="workItem.iid"
:work-item-type="workItemType"
:is-modal="isModal"
:assignees="workItemAssignees && workItemAssignees.assignees.nodes"
:can-set-work-item-metadata="canAssignUnassignUser"
:report-abuse-path="reportAbusePath"
class="gl-pt-5"
@error="updateError = $event"
@has-notes="updateHasNotes"
@openReportAbuse="openReportAbuseDrawer"
/>
<gl-empty-state
v-if="error"
:title="$options.i18n.fetchErrorTitle"
:description="error"
:svg-path="noAccessSvgPath"
/>
</section>
<aside
v-if="workItemsMvc2Enabled"
data-testid="work-item-overview-right-sidebar"
class="work-item-overview-right-sidebar gl-display-none gl-md-display-block"
:class="{ 'is-modal': isModal }"
>
<work-item-attributes-wrapper
:work-item="workItem"
:work-item-parent-id="workItemParentId"
@error="updateError = $event"
/>
</aside>
</div>
</template>
<work-item-detail-modal
v-if="!isModal"

View File

@ -88,7 +88,11 @@ export default {
return !this.canUpdate && !this.dueDate && !this.startDate;
},
labelClass() {
return this.isReadonlyWithNoDates ? 'gl-align-self-center gl-pb-0!' : 'gl-mt-3 gl-pb-0!';
return {
'work-item-field-label': true,
'gl-align-self-center gl-pb-0!': this.isReadonlyWithNoDates,
'gl-mt-3 gl-pb-0!': !this.isReadonlyWithNoDates,
};
},
showDueDateButton() {
return this.canUpdate && !this.showDueDateInput;

View File

@ -259,7 +259,7 @@ export default {
<div class="form-row gl-mb-5 work-item-labels gl-relative gl-flex-nowrap">
<span
:id="labelsTitleId"
class="gl-font-weight-bold gl-mt-2 col-lg-2 col-3 gl-pt-2 min-w-fit-content gl-overflow-wrap-break"
class="gl-font-weight-bold gl-mt-2 col-lg-2 col-3 gl-pt-2 min-w-fit-content gl-overflow-wrap-break work-item-field-label"
data-testid="labels-title"
>{{ __('Labels') }}</span
>
@ -272,7 +272,8 @@ export default {
:loading="isLoading"
:view-only="!canUpdate"
:allow-clear-all="isEditing"
class="gl-flex-grow-1 gl-border gl-border-white gl-rounded-base col-9 gl-align-self-start gl-px-0! gl-mx-2!"
class="gl-flex-grow-1 gl-border gl-border-white gl-rounded-base col-9 gl-align-self-start gl-px-0! gl-mx-2! work-item-field-value"
menu-class="token-selector-menu-class"
data-testid="work-item-labels-input"
:class="{ 'gl-hover-border-gray-200': canUpdate }"
@input="focusTokenSelector"

View File

@ -208,13 +208,13 @@ export default {
class="work-item-dropdown gl-flex-nowrap"
:label="$options.i18n.MILESTONE"
label-for="milestone-value"
label-class="gl-pb-0! gl-mt-3 gl-overflow-wrap-break"
label-class="gl-pb-0! gl-mt-3 gl-overflow-wrap-break work-item-field-label"
label-cols="3"
label-cols-lg="2"
>
<span
v-if="!canUpdate"
class="gl-text-secondary gl-ml-4 gl-mt-3 gl-display-inline-block gl-line-height-normal"
class="gl-text-secondary gl-ml-4 gl-mt-3 gl-display-inline-block gl-line-height-normal work-item-field-value"
data-testid="disabled-text"
>
{{ dropdownText }}
@ -223,7 +223,7 @@ export default {
v-else
id="milestone-value"
data-testid="work-item-milestone-dropdown"
class="gl-pl-0 gl-max-w-full"
class="gl-pl-0 gl-max-w-full work-item-field-value"
:toggle-class="dropdownClasses"
:text="dropdownText"
:loading="updateInProgress"

View File

@ -1,5 +1,8 @@
@import 'mixins_and_variables_and_functions';
$work-item-overview-right-sidebar-width: 340px;
$work-item-sticky-header-height: 52px;
.gl-token-selector-token-container {
display: flex;
align-items: center;
@ -104,3 +107,54 @@
@include gl-font-weight-normal;
}
}
.work-item-overview {
@include media-breakpoint-up(md) {
display: grid;
grid-template-columns: 1fr $work-item-overview-right-sidebar-width;
gap: 2rem;
}
}
.work-item-overview-right-sidebar {
@include media-breakpoint-up(md) {
&.is-modal {
.work-item-attributes-wrapper {
top: 0;
}
}
}
}
.work-item-attributes-wrapper {
.work-item-overview & {
@include media-breakpoint-up(md) {
top: calc(#{$calc-application-header-height} + #{$work-item-sticky-header-height});
height: calc(#{$calc-application-viewport-height} - #{$work-item-sticky-header-height});
margin-bottom: calc(#{$content-wrapper-padding} * -1);
position: sticky;
overflow-y: auto;
overflow-x: hidden;
}
}
}
.work-item-field-label {
.work-item-overview & {
max-width: 30%;
flex: none;
}
}
.work-item-field-value {
.work-item-overview & {
max-width: 65%;
}
}
.token-selector-menu-class {
.work-item-overview & {
width: 100%;
min-width: 100%;
}
}

View File

@ -12,7 +12,7 @@
= s_('Jobs|Use jobs to automate your tasks')
%p
= s_('Jobs|Jobs are the building blocks of a GitLab CI/CD pipeline. Each job has a specific task, like testing code. To set up jobs in a CI/CD pipeline, add a CI/CD configuration file to your project.')
= link_to s_('Jobs|Create CI/CD configuration file'), project_ci_pipeline_editor_path(project), class: 'btn gl-button btn-confirm js-empty-state-button'
= link_button_to s_('Jobs|Create CI/CD configuration file'), project_ci_pipeline_editor_path(project), class: 'js-empty-state-button', variant: :confirm
- else
.nothing-here-block= s_('Jobs|No jobs to show')
- else

View File

@ -40,4 +40,4 @@
= f.gitlab_ui_checkbox_component :active, _('Active'), checkbox_options: { value: @schedule.active, required: false }
.footer-block
= f.submit _('Save pipeline schedule'), pajamas_button: true
= link_to _('Cancel'), pipeline_schedules_path(@project), class: 'btn gl-button btn-default btn-cancel'
= link_button_to _('Cancel'), pipeline_schedules_path(@project)

View File

@ -1,8 +1,8 @@
---
name: key_set_optimizer_ignored_columns
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/125462
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/417515
name: fix_new_blobs_memoization
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/125241
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/417632
milestone: '16.2'
type: development
group: group::project management
group: group::source code
default_enabled: false

View File

@ -58,7 +58,7 @@ NOT_AVAILABLE_TEMPLATES = {
analytics_instrumentation: group_not_available_template('#g_analyze_analytics_instrumentation', '@gitlab-org/analytics-section/analytics-instrumentation/engineers'),
import_integrate_be: group_not_available_template('#g_manage_import_and_integrate', '@gitlab-org/manage/import-and-integrate'),
import_integrate_fe: group_not_available_template('#g_manage_import_and_integrate', '@gitlab-org/manage/import-and-integrate'),
remote_development: group_not_available_template('#f_remote_development', '@gitlab-org/remote-development')
remote_development_be: group_not_available_template('#f_remote_development', '@gitlab-org/maintainers/remote-development/backend')
}.freeze
def note_for_spin_role(spin, role, category)

View File

@ -0,0 +1,83 @@
---
stage: Fulfillment
group: Provision
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Activate GitLab Enterprise Edition (EE) **(PREMIUM SELF)**
When you install a new GitLab instance without a license, only Free features
are enabled. To enable more features in GitLab Enterprise Edition (EE), activate
your instance with an activation code.
## Activate GitLab EE
In GitLab Enterprise Edition 14.1 and later, you need an activation code to activate
your instance.
Prerequisite:
- You must [purchase a subscription](https://about.gitlab.com/pricing/).
- You must be running GitLab Enterprise Edition (EE).
- You must have GitLab 14.1 or later.
- Your instance must be connected to the internet.
To activate your instance with an activation code:
1. Copy the activation code, a 24-character alphanumeric string, from either:
- Your subscription confirmation email.
- The [Customers Portal](https://customers.gitlab.com/customers/sign_in), on the **Manage Purchases** page.
1. Sign in to your GitLab self-managed instance.
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
1. Select **Admin Area**.
1. Select **Subscription**.
1. Paste the activation code in **Activation code**.
1. Read and accept the terms of service.
1. Select **Activate**.
The subscription is activated.
If you have an offline environment,
[activate GitLab EE with a license file or key](../user/admin_area/license_file.md) instead.
If you have questions or need assistance activating your instance,
[contact GitLab Support](https://about.gitlab.com/support/#contact-support).
When [the license expires](../administration/license_file.md#what-happens-when-your-license-expires),
some functionality is locked.
## Verify your GitLab edition
To verify the edition, sign in to GitLab and select
**Help** (**{question-o}**) > **Help**. The GitLab edition and version are listed
at the top of the page.
If you are running GitLab Community Edition, you can upgrade your installation to GitLab
EE. For more details, see [Upgrading between editions](../update/index.md#upgrading-between-editions).
If you have questions or need assistance upgrading from GitLab Community Edition (CE) to EE,
[contact GitLab Support](https://about.gitlab.com/support/#contact-support).
## Troubleshooting
### Cannot activate instance due to connectivity error
This error occurs when you use an activation code to activate your instance, but your instance is unable to connect to the GitLab servers.
You may have connectivity issues due to the following reasons:
- **You have an offline environment**:
- Configure your setup to allow connection to GitLab servers. If connection to GitLab servers is not possible, contact your Sales Representative to request a license key. You can also contact [GitLab support](https://about.gitlab.com/support/#contact-support) if you need help finding your Sales Representative.
- **Customers Portal is not operational**:
- To check for performance or service disruptions, check the Customers Portal [status](https://status.gitlab.com/).
- **Firewall settings**:
- Check if your GitLab instance has an encrypted connection to `customers.gitlab.com` (with IP addresses 172.64.146.11 and 104.18.41.245) on port 443:
```shell
curl --verbose "https://customers.gitlab.com/"
```
- If the curl command returns a failure, either:
- [Configure a proxy](https://docs.gitlab.com/omnibus/settings/environment-variables.html) in `gitlab.rb` to point to your server.
- Contact your network administrator to make changes to the proxy.
- If an SSL inspection appliance is used, you must add the appliance's root CA certificate to `/etc/gitlab/trusted-certs` on the server, then run `gitlab-ctl reconfigure`.

View File

@ -113,7 +113,7 @@ Configure DNS for an alternate SSH hostname such as `altssh.gitlab.example.com`.
## Readiness check
It is strongly recommend that multi-node deployments configure load balancers to use the [readiness check](../user/admin_area/monitoring/health_check.md#readiness) to ensure a node is ready to accept traffic, before routing traffic to it. This is especially important when utilizing Puma, as there is a brief period during a restart where Puma doesn't accept requests.
It is strongly recommend that multi-node deployments configure load balancers to use the [readiness check](../administration/monitoring/health_check.md#readiness) to ensure a node is ready to accept traffic, before routing traffic to it. This is especially important when utilizing Puma, as there is a brief period during a restart where Puma doesn't accept requests.
WARNING:
Using the `all=1` parameter with the readiness check in GitLab versions 15.4 to 15.8 may cause [increased Praefect memory usage](https://gitlab.com/gitlab-org/gitaly/-/issues/4751) and lead to memory errors.

View File

@ -0,0 +1,146 @@
---
stage: Monitor
group: Respond
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Health Check **(FREE SELF)**
GitLab provides liveness and readiness probes to indicate service health and
reachability to required services. These probes report on the status of the
database connection, Redis connection, and access to the file system. These
endpoints [can be provided to schedulers like Kubernetes](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) to hold
traffic until the system is ready or restart the container as needed.
## IP allowlist
To access monitoring resources, the requesting client IP needs to be included in the allowlist.
For details, see [how to add IPs to the allowlist for the monitoring endpoints](../../administration/monitoring/ip_allowlist.md).
## Using the endpoints locally
With default allowlist settings, the probes can be accessed from localhost using the following URLs:
```plaintext
GET http://localhost/-/health
```
```plaintext
GET http://localhost/-/readiness
```
```plaintext
GET http://localhost/-/liveness
```
## Health
Checks whether the application server is running.
It does not verify the database or other services
are running. This endpoint circumvents Rails Controllers
and is implemented as additional middleware `BasicHealthCheck`
very early into the request processing lifecycle.
```plaintext
GET /-/health
```
Example request:
```shell
curl "https://gitlab.example.com/-/health"
```
Example response:
```plaintext
GitLab OK
```
## Readiness
The readiness probe checks whether the GitLab instance is ready
to accept traffic via Rails Controllers. The check by default
does validate only instance-checks.
If the `all=1` parameter is specified, the check also validates
the dependent services (Database, Redis, Gitaly etc.)
and gives a status for each.
```plaintext
GET /-/readiness
GET /-/readiness?all=1
```
Example request:
```shell
curl "https://gitlab.example.com/-/readiness"
```
Example response:
```json
{
"master_check":[{
"status":"failed",
"message": "unexpected Master check result: false"
}],
...
}
```
On failure, the endpoint returns a `503` HTTP status code.
This check is being exempt from Rack Attack.
## Liveness
WARNING:
In GitLab [12.4](https://about.gitlab.com/upcoming-releases/)
the response body of the Liveness check was changed
to match the example below.
Checks whether the application server is running.
This probe is used to know if Rails Controllers
are not deadlocked due to a multi-threading.
```plaintext
GET /-/liveness
```
Example request:
```shell
curl "https://gitlab.example.com/-/liveness"
```
Example response:
On success, the endpoint returns a `200` HTTP status code, and a response like below.
```json
{
"status": "ok"
}
```
On failure, the endpoint returns a `503` HTTP status code.
This check is being exempt from Rack Attack.
## Sidekiq
Learn how to configure the [Sidekiq health checks](../../administration/sidekiq/sidekiq_health_check.md).
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
one might have when setting this up, or when something is changed, or on upgrading, it's
important to describe those, too. Think of things that may go wrong and include them here.
This is important to minimize requests for support, and to avoid doc comments with
questions that you know someone might ask.
Each scenario can be a third-level heading, for example `### Getting error message X`.
If you have none to add when creating a doc, leave this section in place
but commented out to help encourage others to add to it in the future. -->

View File

@ -69,7 +69,7 @@ GitLab Shell path: /opt/gitlab/embedded/service/gitlab-shell
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20501) in GitLab 12.6.
> - Moved to GitLab Premium in 13.9.
This command shows information about your [GitLab license](../../user/admin_area/license.md) and
This command shows information about your [GitLab license](../../administration/license.md) and
how many seats are used. It is only available on GitLab Enterprise
installations: a license cannot be installed into GitLab Community Edition.

View File

@ -0,0 +1,49 @@
---
stage: Anti-Abuse
group: Anti-Abuse
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Git abuse rate limit (administration) **(ULTIMATE SELF)**
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/8066) in GitLab 15.2 [with a flag](../../administration/feature_flags.md) named `git_abuse_rate_limit_feature_flag`. Disabled by default.
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/394996) in GitLab 15.11. Feature flag `git_abuse_rate_limit_feature_flag` removed.
This is the administration documentation. For information about Git abuse rate limiting at the group level, see the [group-level documentation](../../user/group/reporting/git_abuse_rate_limit.md).
Git abuse rate limiting is a feature to automatically [ban users](../../user/admin_area/moderate_users.md#ban-and-unban-users) who download, clone, or fork more than a specified number of repositories in any project in the instance in a given time frame. Banned users cannot sign in to the instance and cannot access any non-public group via HTTP or SSH. The rate limit also applies to users who authenticate with a [personal](../../user/profile/personal_access_tokens.md) or [group access token](../../user/group/settings/group_access_tokens.md).
Git abuse rate limiting does not apply to instance administrators, [deploy tokens](../../user/project/deploy_tokens/index.md), or [deploy keys](../../user/project/deploy_keys/index.md).
How GitLab determines a user's rate limit is under development.
GitLab team members can view more information in this confidential epic:
`https://gitlab.com/groups/gitlab-org/modelops/anti-abuse/-/epics/14`.
## Configure Git abuse rate limiting
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
1. Select **Admin Area**.
1. Select **Settings > Reporting**.
1. Expand **Git abuse rate limit**.
1. Update the Git abuse rate limit settings:
1. Enter a number in the **Number of repositories** field, greater than or equal to `0` and less than or equal to `10,000`. This number specifies the maximum amount of unique repositories a user can download in the specified time period before they're banned. When set to `0`, Git abuse rate limiting is disabled.
1. Enter a number in the **Reporting time period (seconds)** field, greater than or equal to `0` and less than or equal to `86,400` (10 days). This number specifies the time in seconds a user can download the maximum amount of repositories before they're banned. When set to `0`, Git abuse rate limiting is disabled.
1. Optional. Exclude up to `100` users by adding them to the **Excluded users** field. Excluded users are not automatically banned.
1. Add up to `100` users to the **Send notifications to** field. You must select at least one user. All application administrators are selected by default.
1. Optional. Turn on the **Automatically ban users from this namespace when they exceed the specified limits** toggle to enable automatic banning.
1. Select **Save changes**.
## Automatic ban notifications
If automatic banning is disabled, a user is not banned automatically when they exceed the limit. However, notifications are still sent to the users listed under **Send notifications to**. You can use this setup to determine the correct values of the rate limit settings before enabling automatic banning.
If automatic banning is enabled, an email notification is sent when a user is about to be banned, and the user is automatically banned from the GitLab instance.
## Unban a user
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
1. Select **Admin Area**.
1. Select **Overview > Users**.
1. Select the **Banned** tab and search for the account you want to unban.
1. From the **User administration** dropdown list select **Unban user**.
1. On the confirmation dialog, select **Unban user**.

View File

@ -0,0 +1,37 @@
---
type: reference
stage: Data Stores
group: Tenant Scale
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Rate limit on Projects API **(FREE SELF)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/112283) in GitLab 15.10 with a [flag](../feature_flags.md) named `rate_limit_for_unauthenticated_projects_api_access`. Disabled by default.
> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/391922) on May 08, 2023.
> - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/119603) in GitLab 16.0 by default.
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/120445) in GitLab 16.0. Feature flag `rate_limit_for_unauthenticated_projects_api_access` removed.
You can configure the rate limit per IP address for unauthenticated requests to the [list all projects API](../../api/projects.md#list-all-projects).
To change the rate limit:
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
1. Select **Admin Area**.
1. Select **Settings > Network**.
1. Expand **Projects API rate limit**.
1. In the **Maximum requests per 10 minutes per IP address** text box, enter the new value.
1. Select **Save changes**.
The rate limit:
- Applies per IP address.
- Doesn't apply to authenticated requests.
- Can be set to 0 to disable rate limiting.
The default value of the rate limit is `400`.
Requests over the rate limit are logged into the `auth.log` file.
For example, if you set a limit of 400, unauthenticated requests to the `GET /projects` API endpoint that
exceed a rate of 400 within 10 minutes are blocked. Access to the endpoint is restored after ten minutes have elapsed.

View File

@ -0,0 +1,34 @@
---
type: reference
stage: Manage
group: Authentication and Authorization
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Rate limits on Users API **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78364) in GitLab 14.8.
You can configure the per user rate limit for requests to [Users API](../../api/users.md).
To change the rate limit:
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
1. Select **Admin Area**.
1. Select **Settings > Network**.
1. Expand **Users API rate limit**.
1. In the **Maximum requests per 10 minutes** text box, enter the new value.
1. Optional. In the **Users to exclude from the rate limit** box, list users allowed to exceed the limit.
1. Select **Save changes**.
This limit is:
- Applied independently per user.
- Not applied per IP address.
The default value is `300`.
Requests over the rate limit are logged into the `auth.log` file.
For example, if you set a limit of 300, requests to the `GET /users/:id` API endpoint
exceeding a rate of 300 per 10 minutes are blocked. Access to the endpoint is allowed after ten minutes have elapsed.

View File

@ -0,0 +1,33 @@
---
stage: Create
group: Source Code
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
# Rate limits on Git SSH operations **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78373) in GitLab 14.7 [with a flag](../feature_flags.md) named `rate_limit_gitlab_shell`. Available by default without a feature flag from 15.8.
GitLab applies rate limits to Git operations that use SSH by user account and project. When the rate limit is exceeded, GitLab rejects
further connection requests from that user for the project.
The rate limit applies at the Git command ([plumbing](https://git-scm.com/book/en/v2/Git-Internals-Plumbing-and-Porcelain)) level.
Each command has a rate limit of 600 per minute. For example:
- `git push` has a rate limit of 600 per minute.
- `git pull` has its own rate limit of 600 per minute.
Because the same commands are shared by `git-upload-pack`, `git pull`, and `git clone`, they share a rate limit.
Users on self-managed GitLab can disable this rate limit.
## Configure GitLab Shell operation limit
`Git operations using SSH` is enabled by default. Defaults to 600 per user per minute.
1. On the left sidebar, select **Your work > Admin Area**.
1. On the left sidebar, select **Settings > Network**.
1. Expand **Git SSH operations rate limit**.
1. Enter a value for **Maximum number of Git operations per minute**.
1. Select **Save changes**.

View File

@ -0,0 +1,29 @@
---
stage: none
group: unassigned
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---
# Rate limits on raw endpoints **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30635) in GitLab 12.2.
This setting defaults to `300` requests per minute, and allows you to rate limit the requests to raw endpoints:
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
1. Select **Admin Area**.
1. Select **Settings > Network**.
1. Expand **Performance optimization**.
For example, requests over `300` per minute to `https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/controllers/application_controller.rb` are blocked. Access to the raw file is released after 1 minute.
![Rate limits on raw endpoints](../../user/admin_area/settings/img/rate_limits_on_raw_endpoints.png)
This limit is:
- Applied independently per project, per file path.
- Not applied per IP address.
- Active by default. To disable, set the option to `0`.
Requests over the rate limit are logged into `auth.log`.

View File

@ -0,0 +1,43 @@
---
type: reference, howto
stage: Manage
group: Authentication and Authorization
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Configure SCIM for self-managed GitLab instances **(PREMIUM SELF)**
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/8902) in GitLab 15.8.
You can use the open standard System for Cross-domain Identity Management (SCIM) to automatically:
- Create users.
- Block users.
The [internal GitLab SCIM API](../../development/internal_api/index.md#instance-scim-api) implements part of [the RFC7644 protocol](https://www.rfc-editor.org/rfc/rfc7644).
If you are a GitLab.com user, see [configuring SCIM for GitLab.com groups](../../user/group/saml_sso/scim_setup.md).
## Configure GitLab
Prerequisites:
- Configure [SAML single sign-on](../../integration/saml.md).
To configure GitLab SCIM:
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
1. Select **Admin Area**.
1. Select **Settings > General**.
1. Expand the **SCIM Token** section and select **Generate a SCIM token**.
1. For configuration of your identity provider, save the:
- Token from the **Your SCIM token** field.
- URL from the **SCIM API endpoint URL** field.
## Remove access
Removing or deactivating a user on the identity provider blocks the user on
the GitLab instance, while the SCIM identity remains linked to the GitLab user.
To update the user SCIM identity, use the
[internal GitLab SCIM API](../../development/internal_api/index.md#update-a-single-scim-provisioned-user-1).

View File

@ -38,7 +38,7 @@ Have a look at some of our most popular topics:
| [Two-factor authentication](user/profile/account/two_factor_authentication.md) | Improve the security of your GitLab account. |
| [GitLab groups](user/group/index.md) | Manage projects together. |
| [Keyword reference for the `.gitlab-ci.yml` file](ci/yaml/index.md) | Available configuration options for `.gitlab-ci.yml` files. |
| [Activate GitLab EE with a license](user/admin_area/license.md) | Activate GitLab Enterprise Edition functionality with a license. |
| [Activate GitLab EE with a license](administration/license.md) | Activate GitLab Enterprise Edition functionality with a license. |
| [Back up and restore GitLab](administration/backup_restore/index.md) | Backing up and restoring GitLab self-managed instances. |
| [GitLab release and maintenance policy](policy/maintenance.md) | Policies for version naming and cadence, and also upgrade recommendations. |
| [Elasticsearch integration](integration/advanced_search/elasticsearch.md) | Integrate Elasticsearch with GitLab to enable advanced search. |

View File

@ -50,7 +50,7 @@ installation.
## License
- [Add a license](../user/admin_area/license.md) or [start a free trial](https://about.gitlab.com/free-trial/):
- [Add a license](../administration/license.md) or [start a free trial](https://about.gitlab.com/free-trial/):
Activate all GitLab Enterprise Edition functionality with a license.
- [Pricing](https://about.gitlab.com/pricing/): Pricing for the different tiers.

View File

@ -179,7 +179,7 @@ To enable advanced search:
NOTE:
To see the **Advanced Search** section, you need an active GitLab Premium
[license](../../user/admin_area/license.md).
[license](../../administration/license.md).
1. Configure the [advanced search settings](#advanced-search-configuration) for
your Elasticsearch cluster. Do not enable **Search with Elasticsearch enabled**

View File

@ -15,7 +15,7 @@ New paid features will not be released in Bronze and Starter tiers after GitLab
The following features remain available to Bronze and Starter customers, even though
the tiers are no longer mentioned in GitLab documentation:
- [Activate GitLab EE with a license](../user/admin_area/license.md)
- [Activate GitLab EE with a license](../administration/license.md)
- [Add a help message to the sign-in page](../administration/settings/help_page.md#add-a-help-message-to-the-sign-in-page)
- [Burndown and burnup charts](../user/project/milestones/burndown_and_burnup_charts.md) in the [Milestone View](../user/project/milestones/index.md#burndown-charts),
- [Code owners](../user/project/codeowners/index.md)

View File

@ -15,7 +15,7 @@ To subscribe to GitLab for a GitLab self-managed installation:
1. Go to the [Customers Portal](https://customers.gitlab.com/) and purchase a GitLab self-managed plan.
1. After purchase, an activation code is sent to the email address associated with the Customers Portal account.
You must [add this code to your GitLab instance](../../user/admin_area/license.md).
You must [add this code to your GitLab instance](../../administration/license.md).
NOTE:
If you're purchasing a subscription for an existing **Free** GitLab self-managed
@ -132,7 +132,7 @@ To enable subscription data synchronization you must have:
- GitLab Enterprise Edition (EE), version 14.1 or later.
- Connection to the internet, and must not have an offline environment.
- [Activated](../../user/admin_area/license.md) your instance with an activation code.
- [Activated](../../administration/license.md) your instance with an activation code.
When your instance is activated, and data is synchronized, the following processes are automated:
@ -367,7 +367,7 @@ You can hover your mouse on the **Renew** button to see the date when it will be
1. Enter the number of [users over subscription](#users-over-subscription) in the second box for the user overage incurred in your previous subscription term.
1. Review your renewal details and complete the payment process.
1. An activation code for the renewal term is available on the [Manage Purchases](https://customers.gitlab.com/subscriptions) page on the relevant subscription card. Select **Copy activation code** to get a copy.
1. [Add the activation code](../../user/admin_area/license.md) to your instance.
1. [Add the activation code](../../administration/license.md) to your instance.
An invoice is generated for the renewal and available for viewing or download on the [View invoices](https://customers.gitlab.com/receipts) page. If you have difficulty during the renewal process, contact our [support team](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=360000071293) for assistance.

View File

@ -299,6 +299,7 @@ and [Helm Chart deployments](https://docs.gitlab.com/charts/). They come with ap
- Geo: Since the migration of project designs to SSF, [missing design repositories are being incorrectly flagged as failing verification](https://gitlab.com/gitlab-org/gitlab/-/issues/414279). This is not a result of an actual replication/verification failure but an invalid internal state for these missing repositories inside Geo and results in errors in the logs and the verification progress reporting a failed state for these design repositories. You could be impacted by this issue even if you have not imported projects.
- Impacted versions: GitLab versions 16.1.x.
- Versions containing fix: GitLab 16.2.0 and later.
- For self-compiled installations: You must remove any settings related to Puma worker killer from the `puma.rb` configuration file, since those have been [removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/118645). For more information, see the [`puma.rb.example`](https://gitlab.com/gitlab-org/gitlab/-/blob/16-0-stable-ee/config/puma.rb.example) file.
### 16.0.0
@ -323,6 +324,9 @@ and [Helm Chart deployments](https://docs.gitlab.com/charts/). They come with ap
- Geo: Some project imports do not initialize wiki repositories on project creation. Since the migration of project wikis to SSF, [missing wiki repositories are being incorrectly flagged as failing verification](https://gitlab.com/gitlab-org/gitlab/-/issues/409704). This is not a result of an actual replication/verification failure but an invalid internal state for these missing repositories inside Geo and results in errors in the logs and the verification progress reporting a failed state for these wiki repositories. If you have not imported projects you are not impacted by this issue.
- Impacted versions: GitLab versions 15.11.x, 16.0.x, and 16.1.0 - 16.1.2.
- Versions containing fix: GitLab 16.1.3 and later.
- Geo: A [bug](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/7841) in the built-in `pg-upgrade` tool prevents upgrading the bundled PostgreSQL database to version 13. This leaves the secondary site in a broken state, and prevents upgrading the Geo installation to GitLab 16.x ([PostgreSQL 12 support has removed in 16.0](deprecations.md#postgresql-12-deprecated) and later releases). This occurs on secondary sites using the bundled PostgreSQL software, running both the secondary main Rails database and tracking database on the same node. There is a manual [workaround](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/7841#workaround) for those impacted until a fix is backported to 15.11.
- Impacted versions: GitLab versions 15.2 - 15.11
- Version 16.0 and later are not impacted. Note, 15.11 is a mandatory upgrade stop on the way to 16.0.
### 15.11.0
@ -332,6 +336,9 @@ and [Helm Chart deployments](https://docs.gitlab.com/charts/). They come with ap
- Geo: Some project imports do not initialize wiki repositories on project creation. Since the migration of project wikis to SSF, [missing wiki repositories are being incorrectly flagged as failing verification](https://gitlab.com/gitlab-org/gitlab/-/issues/409704). This is not a result of an actual replication/verification failure but an invalid internal state for these missing repositories inside Geo and results in errors in the logs and the verification progress reporting a failed state for these wiki repositories. If you have not imported projects you are not impacted by this issue.
- Impacted versions: GitLab versions 15.11.x, 16.0.x, and 16.1.0 - 16.1.2.
- Versions containing fix: GitLab 16.1.3 and later.
- Geo: A [bug](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/7841) in the built-in `pg-upgrade` tool prevents upgrading the bundled PostgreSQL database to version 13. This leaves the secondary site in a broken state, and prevents upgrading the Geo installation to GitLab 16.x ([PostgreSQL 12 support has removed in 16.0](deprecations.md#postgresql-12-deprecated) and later releases). This occurs on secondary sites using the bundled PostgreSQL software, running both the secondary main Rails database and tracking database on the same node. There is a manual [workaround](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/7841#workaround) for those impacted until a fix is backported to 15.11.
- Impacted versions: GitLab versions 15.2 - 15.11
- Version 16.0 and later are not impacted. Note, 15.11 is a mandatory upgrade stop on the way to 16.0.
### 15.10.5

View File

@ -69,7 +69,7 @@ The steps can be summed up to:
If you want to use `dpkg`/`rpm` instead of `apt-get`/`yum`, go through the first
step to find the current GitLab version, then follow
[Upgrade using a manually-downloaded package](index.md#upgrade-using-a-manually-downloaded-package),
and then [add your license](../../user/admin_area/license.md).
and then [add your license](../../administration/license.md).
1. Install the `gitlab-ee` package. The install automatically
uninstalls the `gitlab-ce` package on your GitLab server. `reconfigure`
@ -99,7 +99,7 @@ The steps can be summed up to:
sudo gitlab-ctl reconfigure
```
1. Now activate GitLab Enterprise Edition by [adding your license](../../user/admin_area/license.md).
1. Now activate GitLab Enterprise Edition by [adding your license](../../administration/license.md).
1. After you confirm that GitLab is working as expected, you may remove the old
Community Edition repository:

View File

@ -1,83 +1,11 @@
---
stage: Fulfillment
group: Provision
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
redirect_to: '../../administration/license.md'
remove_date: '2023-10-11'
---
# Activate GitLab Enterprise Edition (EE) **(PREMIUM SELF)**
This document was moved to [another location](../../administration/license.md).
When you install a new GitLab instance without a license, only Free features
are enabled. To enable more features in GitLab Enterprise Edition (EE), activate
your instance with an activation code.
## Activate GitLab EE
In GitLab Enterprise Edition 14.1 and later, you need an activation code to activate
your instance.
Prerequisite:
- You must [purchase a subscription](https://about.gitlab.com/pricing/).
- You must be running GitLab Enterprise Edition (EE).
- You must have GitLab 14.1 or later.
- Your instance must be connected to the internet.
To activate your instance with an activation code:
1. Copy the activation code, a 24-character alphanumeric string, from either:
- Your subscription confirmation email.
- The [Customers Portal](https://customers.gitlab.com/customers/sign_in), on the **Manage Purchases** page.
1. Sign in to your GitLab self-managed instance.
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
1. Select **Admin Area**.
1. Select **Subscription**.
1. Paste the activation code in **Activation code**.
1. Read and accept the terms of service.
1. Select **Activate**.
The subscription is activated.
If you have an offline environment,
[activate GitLab EE with a license file or key](../../administration/license_file.md) instead.
If you have questions or need assistance activating your instance,
[contact GitLab Support](https://about.gitlab.com/support/#contact-support).
When [the license expires](../../administration/license_file.md#what-happens-when-your-license-expires),
some functionality is locked.
## Verify your GitLab edition
To verify the edition, sign in to GitLab and select
**Help** (**{question-o}**) > **Help**. The GitLab edition and version are listed
at the top of the page.
If you are running GitLab Community Edition, you can upgrade your installation to GitLab
EE. For more details, see [Upgrading between editions](../../update/index.md#upgrading-between-editions).
If you have questions or need assistance upgrading from GitLab Community Edition (CE) to EE,
[contact GitLab Support](https://about.gitlab.com/support/#contact-support).
## Troubleshooting
### Cannot activate instance due to connectivity error
This error occurs when you use an activation code to activate your instance, but your instance is unable to connect to the GitLab servers.
You may have connectivity issues due to the following reasons:
- **You have an offline environment**:
- Configure your setup to allow connection to GitLab servers. If connection to GitLab servers is not possible, contact your Sales Representative to request a license key. You can also contact [GitLab support](https://about.gitlab.com/support/#contact-support) if you need help finding your Sales Representative.
- **Customers Portal is not operational**:
- To check for performance or service disruptions, check the Customers Portal [status](https://status.gitlab.com/).
- **Firewall settings**:
- Check if your GitLab instance has an encrypted connection to `customers.gitlab.com` (with IP addresses 172.64.146.11 and 104.18.41.245) on port 443:
```shell
curl --verbose "https://customers.gitlab.com/"
```
- If the curl command returns a failure, either:
- [Configure a proxy](https://docs.gitlab.com/omnibus/settings/environment-variables.html) in `gitlab.rb` to point to your server.
- Contact your network administrator to make changes to the proxy.
- If an SSL inspection appliance is used, you must add the appliance's root CA certificate to `/etc/gitlab/trusted-certs` on the server, then run `gitlab-ctl reconfigure`.
<!-- This redirect file can be deleted after <2023-10-11>. -->
<!-- Redirects that point to other docs in the same project expire in three months. -->
<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->

View File

@ -1,146 +1,11 @@
---
stage: Monitor
group: Respond
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
redirect_to: '../../../administration/monitoring/health_check.md'
remove_date: '2023-10-12'
---
# Health Check **(FREE SELF)**
This document was moved to [another location](../../../administration/monitoring/health_check.md).
GitLab provides liveness and readiness probes to indicate service health and
reachability to required services. These probes report on the status of the
database connection, Redis connection, and access to the file system. These
endpoints [can be provided to schedulers like Kubernetes](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) to hold
traffic until the system is ready or restart the container as needed.
## IP allowlist
To access monitoring resources, the requesting client IP needs to be included in the allowlist.
For details, see [how to add IPs to the allowlist for the monitoring endpoints](../../../administration/monitoring/ip_allowlist.md).
## Using the endpoints locally
With default allowlist settings, the probes can be accessed from localhost using the following URLs:
```plaintext
GET http://localhost/-/health
```
```plaintext
GET http://localhost/-/readiness
```
```plaintext
GET http://localhost/-/liveness
```
## Health
Checks whether the application server is running.
It does not verify the database or other services
are running. This endpoint circumvents Rails Controllers
and is implemented as additional middleware `BasicHealthCheck`
very early into the request processing lifecycle.
```plaintext
GET /-/health
```
Example request:
```shell
curl "https://gitlab.example.com/-/health"
```
Example response:
```plaintext
GitLab OK
```
## Readiness
The readiness probe checks whether the GitLab instance is ready
to accept traffic via Rails Controllers. The check by default
does validate only instance-checks.
If the `all=1` parameter is specified, the check also validates
the dependent services (Database, Redis, Gitaly etc.)
and gives a status for each.
```plaintext
GET /-/readiness
GET /-/readiness?all=1
```
Example request:
```shell
curl "https://gitlab.example.com/-/readiness"
```
Example response:
```json
{
"master_check":[{
"status":"failed",
"message": "unexpected Master check result: false"
}],
...
}
```
On failure, the endpoint returns a `503` HTTP status code.
This check is being exempt from Rack Attack.
## Liveness
WARNING:
In GitLab [12.4](https://about.gitlab.com/upcoming-releases/)
the response body of the Liveness check was changed
to match the example below.
Checks whether the application server is running.
This probe is used to know if Rails Controllers
are not deadlocked due to a multi-threading.
```plaintext
GET /-/liveness
```
Example request:
```shell
curl "https://gitlab.example.com/-/liveness"
```
Example response:
On success, the endpoint returns a `200` HTTP status code, and a response like below.
```json
{
"status": "ok"
}
```
On failure, the endpoint returns a `503` HTTP status code.
This check is being exempt from Rack Attack.
## Sidekiq
Learn how to configure the [Sidekiq health checks](../../../administration/sidekiq/sidekiq_health_check.md).
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
one might have when setting this up, or when something is changed, or on upgrading, it's
important to describe those, too. Think of things that may go wrong and include them here.
This is important to minimize requests for support, and to avoid doc comments with
questions that you know someone might ask.
Each scenario can be a third-level heading, for example `### Getting error message X`.
If you have none to add when creating a doc, leave this section in place
but commented out to help encourage others to add to it in the future. -->
<!-- This redirect file can be deleted after <2023-10-12>. -->
<!-- Redirects that point to other docs in the same project expire in three months. -->
<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->

View File

@ -1,49 +1,11 @@
---
stage: Anti-Abuse
group: Anti-Abuse
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
redirect_to: '../../../administration//reporting/git_abuse_rate_limit.md'
remove_date: '2023-10-12'
---
# Git abuse rate limit (administration) **(ULTIMATE SELF)**
This document was moved to [another location](../../../administration//reporting/git_abuse_rate_limit.md).
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/8066) in GitLab 15.2 [with a flag](../../../administration/feature_flags.md) named `git_abuse_rate_limit_feature_flag`. Disabled by default.
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/394996) in GitLab 15.11. Feature flag `git_abuse_rate_limit_feature_flag` removed.
This is the administration documentation. For information about Git abuse rate limiting at the group level, see the [group-level documentation](../../group/reporting/git_abuse_rate_limit.md).
Git abuse rate limiting is a feature to automatically [ban users](../moderate_users.md#ban-and-unban-users) who download, clone, or fork more than a specified number of repositories in any project in the instance in a given time frame. Banned users cannot sign in to the instance and cannot access any non-public group via HTTP or SSH. The rate limit also applies to users who authenticate with a [personal](../../../user/profile/personal_access_tokens.md) or [group access token](../../../user/group/settings/group_access_tokens.md).
Git abuse rate limiting does not apply to instance administrators, [deploy tokens](../../../user/project/deploy_tokens/index.md), or [deploy keys](../../../user/project/deploy_keys/index.md).
How GitLab determines a user's rate limit is under development.
GitLab team members can view more information in this confidential epic:
`https://gitlab.com/groups/gitlab-org/modelops/anti-abuse/-/epics/14`.
## Configure Git abuse rate limiting
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
1. Select **Admin Area**.
1. Select **Settings > Reporting**.
1. Expand **Git abuse rate limit**.
1. Update the Git abuse rate limit settings:
1. Enter a number in the **Number of repositories** field, greater than or equal to `0` and less than or equal to `10,000`. This number specifies the maximum amount of unique repositories a user can download in the specified time period before they're banned. When set to `0`, Git abuse rate limiting is disabled.
1. Enter a number in the **Reporting time period (seconds)** field, greater than or equal to `0` and less than or equal to `86,400` (10 days). This number specifies the time in seconds a user can download the maximum amount of repositories before they're banned. When set to `0`, Git abuse rate limiting is disabled.
1. Optional. Exclude up to `100` users by adding them to the **Excluded users** field. Excluded users are not automatically banned.
1. Add up to `100` users to the **Send notifications to** field. You must select at least one user. All application administrators are selected by default.
1. Optional. Turn on the **Automatically ban users from this namespace when they exceed the specified limits** toggle to enable automatic banning.
1. Select **Save changes**.
## Automatic ban notifications
If automatic banning is disabled, a user is not banned automatically when they exceed the limit. However, notifications are still sent to the users listed under **Send notifications to**. You can use this setup to determine the correct values of the rate limit settings before enabling automatic banning.
If automatic banning is enabled, an email notification is sent when a user is about to be banned, and the user is automatically banned from the GitLab instance.
## Unban a user
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
1. Select **Admin Area**.
1. Select **Overview > Users**.
1. Select the **Banned** tab and search for the account you want to unban.
1. From the **User administration** dropdown list select **Unban user**.
1. On the confirmation dialog, select **Unban user**.
<!-- This redirect file can be deleted after <2023-10-12>. -->
<!-- Redirects that point to other docs in the same project expire in three months. -->
<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->

View File

@ -1,37 +1,11 @@
---
type: reference
stage: Data Stores
group: Tenant Scale
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
redirect_to: '../../../administration/settings/rate_limit_on_projects_api.md'
remove_date: '2023-10-12'
---
# Rate limit on Projects API **(FREE SELF)**
This document was moved to [another location](../../../administration/settings/rate_limit_on_projects_api.md).
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/112283) in GitLab 15.10 with a [flag](../../../administration/feature_flags.md) named `rate_limit_for_unauthenticated_projects_api_access`. Disabled by default.
> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/391922) on May 08, 2023.
> - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/119603) in GitLab 16.0 by default.
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/120445) in GitLab 16.0. Feature flag `rate_limit_for_unauthenticated_projects_api_access` removed.
You can configure the rate limit per IP address for unauthenticated requests to the [list all projects API](../../../api/projects.md#list-all-projects).
To change the rate limit:
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
1. Select **Admin Area**.
1. Select **Settings > Network**.
1. Expand **Projects API rate limit**.
1. In the **Maximum requests per 10 minutes per IP address** text box, enter the new value.
1. Select **Save changes**.
The rate limit:
- Applies per IP address.
- Doesn't apply to authenticated requests.
- Can be set to 0 to disable rate limiting.
The default value of the rate limit is `400`.
Requests over the rate limit are logged into the `auth.log` file.
For example, if you set a limit of 400, unauthenticated requests to the `GET /projects` API endpoint that
exceed a rate of 400 within 10 minutes are blocked. Access to the endpoint is restored after ten minutes have elapsed.
<!-- This redirect file can be deleted after <2023-10-12>. -->
<!-- Redirects that point to other docs in the same project expire in three months. -->
<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->

View File

@ -1,34 +1,11 @@
---
type: reference
stage: Manage
group: Authentication and Authorization
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
redirect_to: '../../../administration/settings/rate_limit_on_users_api.md'
remove_date: '2023-10-12'
---
# Rate limits on Users API **(FREE SELF)**
This document was moved to [another location](../../../administration/settings/rate_limit_on_users_api.md).
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78364) in GitLab 14.8.
You can configure the per user rate limit for requests to [Users API](../../../api/users.md).
To change the rate limit:
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
1. Select **Admin Area**.
1. Select **Settings > Network**.
1. Expand **Users API rate limit**.
1. In the **Maximum requests per 10 minutes** text box, enter the new value.
1. Optional. In the **Users to exclude from the rate limit** box, list users allowed to exceed the limit.
1. Select **Save changes**.
This limit is:
- Applied independently per user.
- Not applied per IP address.
The default value is `300`.
Requests over the rate limit are logged into the `auth.log` file.
For example, if you set a limit of 300, requests to the `GET /users/:id` API endpoint
exceeding a rate of 300 per 10 minutes are blocked. Access to the endpoint is allowed after ten minutes have elapsed.
<!-- This redirect file can be deleted after <2023-10-12>. -->
<!-- Redirects that point to other docs in the same project expire in three months. -->
<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->

View File

@ -1,33 +1,11 @@
---
stage: Create
group: Source Code
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
redirect_to: '../../../administration/settings/rate_limits_on_git_ssh_operations.md'
remove_date: '2023-10-12'
---
# Rate limits on Git SSH operations **(FREE SELF)**
This document was moved to [another location](../../../administration/settings/rate_limits_on_git_ssh_operations.md).
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78373) in GitLab 14.7 [with a flag](../../../administration/feature_flags.md) named `rate_limit_gitlab_shell`. Available by default without a feature flag from 15.8.
GitLab applies rate limits to Git operations that use SSH by user account and project. When the rate limit is exceeded, GitLab rejects
further connection requests from that user for the project.
The rate limit applies at the Git command ([plumbing](https://git-scm.com/book/en/v2/Git-Internals-Plumbing-and-Porcelain)) level.
Each command has a rate limit of 600 per minute. For example:
- `git push` has a rate limit of 600 per minute.
- `git pull` has its own rate limit of 600 per minute.
Because the same commands are shared by `git-upload-pack`, `git pull`, and `git clone`, they share a rate limit.
Users on self-managed GitLab can disable this rate limit.
## Configure GitLab Shell operation limit
`Git operations using SSH` is enabled by default. Defaults to 600 per user per minute.
1. On the left sidebar, select **Your work > Admin Area**.
1. On the left sidebar, select **Settings > Network**.
1. Expand **Git SSH operations rate limit**.
1. Enter a value for **Maximum number of Git operations per minute**.
1. Select **Save changes**.
<!-- This redirect file can be deleted after <2023-10-12>. -->
<!-- Redirects that point to other docs in the same project expire in three months. -->
<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->

View File

@ -1,29 +1,11 @@
---
stage: none
group: unassigned
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
redirect_to: '../../../administration/settings/rate_limits_on_raw_endpoints.md'
remove_date: '2023-10-12'
---
# Rate limits on raw endpoints **(FREE SELF)**
This document was moved to [another location](../../../administration/settings/rate_limits_on_raw_endpoints.md).
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30635) in GitLab 12.2.
This setting defaults to `300` requests per minute, and allows you to rate limit the requests to raw endpoints:
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
1. Select **Admin Area**.
1. Select **Settings > Network**.
1. Expand **Performance optimization**.
For example, requests over `300` per minute to `https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/controllers/application_controller.rb` are blocked. Access to the raw file is released after 1 minute.
![Rate limits on raw endpoints](img/rate_limits_on_raw_endpoints.png)
This limit is:
- Applied independently per project, per file path.
- Not applied per IP address.
- Active by default. To disable, set the option to `0`.
Requests over the rate limit are logged into `auth.log`.
<!-- This redirect file can be deleted after <2023-10-12>. -->
<!-- Redirects that point to other docs in the same project expire in three months. -->
<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->

View File

@ -1,43 +1,11 @@
---
type: reference, howto
stage: Manage
group: Authentication and Authorization
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
redirect_to: '../../../administration/settings/scim_setup.md'
remove_date: '2023-10-12'
---
# Configure SCIM for self-managed GitLab instances **(PREMIUM SELF)**
This document was moved to [another location](../../../administration/settings/scim_setup.md).
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/8902) in GitLab 15.8.
You can use the open standard System for Cross-domain Identity Management (SCIM) to automatically:
- Create users.
- Block users.
The [internal GitLab SCIM API](../../../development/internal_api/index.md#instance-scim-api) implements part of [the RFC7644 protocol](https://www.rfc-editor.org/rfc/rfc7644).
If you are a GitLab.com user, see [configuring SCIM for GitLab.com groups](../../../user/group/saml_sso/scim_setup.md).
## Configure GitLab
Prerequisites:
- Configure [SAML single sign-on](../../../integration/saml.md).
To configure GitLab SCIM:
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
1. Select **Admin Area**.
1. Select **Settings > General**.
1. Expand the **SCIM Token** section and select **Generate a SCIM token**.
1. For configuration of your identity provider, save the:
- Token from the **Your SCIM token** field.
- URL from the **SCIM API endpoint URL** field.
## Remove access
Removing or deactivating a user on the identity provider blocks the user on
the GitLab instance, while the SCIM identity remains linked to the GitLab user.
To update the user SCIM identity, use the
[internal GitLab SCIM API](../../../development/internal_api/index.md#update-a-single-scim-provisioned-user-1).
<!-- This redirect file can be deleted after <2023-10-12>. -->
<!-- Redirects that point to other docs in the same project expire in three months. -->
<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->

View File

@ -182,7 +182,7 @@ In your Okta SCIM application, check that the SCIM **Base URL** is correct and p
SCIM API endpoint URL. Check the following documentation to find information on this URL for:
- [GitLab.com groups](scim_setup.md#configure-gitlab).
- [Self-managed GitLab instances](../../admin_area/settings/scim_setup.md#configure-gitlab).
- [Self-managed GitLab instances](../../../administration/settings/scim_setup.md#configure-gitlab).
For self-managed GitLab instances, ensure that GitLab is publicly available so Okta can connect to it. If needed,
you can [allow access to Okta IP addresses](https://help.okta.com/en-us/Content/Topics/Security/ip-address-allow-listing.htm)

View File

@ -162,7 +162,7 @@ Prerequisites:
- You need to [authenticate with the API](../../../api/rest/index.md#authentication). If authenticating with a personal access token, it must be configured with the `read_api` scope.
Authentication tokens (Job Token or Personal Access Token) can be provided for `terraform` in your `~/.terraformrc` file:
Authentication tokens (Job Token or Personal Access Token) can be provided for `terraform` in your `~/.terraformrc` or `%APPDATA%/terraform.rc` file:
```terraform
credentials "gitlab.com" {

View File

@ -406,12 +406,20 @@ module Gitlab
return [] if newrevs.empty?
newrevs = newrevs.uniq.sort
if Feature.enabled?(:fix_new_blobs_memoization, container)
@new_blobs ||= {}
@new_blobs[newrevs] ||= blobs(
['--not', '--all', '--not'] + newrevs,
with_paths: true,
dynamic_timeout: dynamic_timeout
).to_a
else
@new_blobs ||= Hash.new do |h, revs|
h[revs] = blobs(['--not', '--all', '--not'] + newrevs, with_paths: true, dynamic_timeout: dynamic_timeout)
end
@new_blobs ||= Hash.new do |h, revs|
h[revs] = blobs(['--not', '--all', '--not'] + newrevs, with_paths: true, dynamic_timeout: dynamic_timeout)
@new_blobs[newrevs]
end
@new_blobs[newrevs]
end
# List blobs reachable via a set of revisions. Supports the

View File

@ -67,11 +67,7 @@ module Gitlab
.select(finder_strategy.final_projections)
.where("count <> 0") # filter out the initializer row
if Feature.enabled?(:key_set_optimizer_ignored_columns)
model.select(Arel.star).from(q.arel.as(table_name))
else
model.from(q.arel.as(table_name))
end
model.select(Arel.star).from(q.arel.as(table_name))
end
private

View File

@ -31,7 +31,7 @@ module Gitlab
end
def final_projections
if @model.default_select_columns.is_a?(Array) && Feature.enabled?(:key_set_optimizer_ignored_columns)
if @model.default_select_columns.is_a?(Array)
@model.default_select_columns.map { |column| "(#{RECORDS_COLUMN}).#{column.name}" }
else
["(#{RECORDS_COLUMN}).*"]

View File

@ -247,11 +247,7 @@ module Gitlab
scope.dup.where(where_value).reorder(self) # rubocop: disable CodeReuse/ActiveRecord
end
if Feature.enabled?(:key_set_optimizer_ignored_columns)
scope.model.select(scope.select_values).from_union(scopes, remove_duplicates: false, remove_order: false)
else
scope.model.from_union(scopes, remove_duplicates: false, remove_order: false)
end
scope.model.select(scope.select_values).from_union(scopes, remove_duplicates: false, remove_order: false)
end
def to_sql_literal(column_definitions)

View File

@ -1920,6 +1920,12 @@ msgstr ""
msgid "AI|Code Explanation"
msgstr ""
msgid "AI|Creates issue description based on a short prompt"
msgstr ""
msgid "AI|Description is required"
msgstr ""
msgid "AI|Enabling these features is your acceptance of the %{link_start}GitLab Testing Agreement%{link_end}."
msgstr ""
@ -1938,6 +1944,9 @@ msgstr ""
msgid "AI|For example: Organizations should be able to forecast into the future by using value stream analytics charts. This feature would help them understand how their metrics are trending."
msgstr ""
msgid "AI|Generate issue description"
msgstr ""
msgid "AI|Helpful"
msgstr ""
@ -21856,6 +21865,9 @@ msgstr ""
msgid "GroupSaml|Your SCIM token"
msgstr ""
msgid "GroupSelect|An error occurred fetching the groups. Please refresh the page to try again."
msgstr ""
msgid "GroupSelect|No matching results"
msgstr ""
@ -23041,6 +23053,9 @@ msgstr ""
msgid "IdentityVerification|You've reached the maximum amount of resends. Wait %{interval} and try again."
msgstr ""
msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} and try again."
msgstr ""
msgid "IdentityVerification|You've reached the maximum amount of tries. Wait %{interval} or send a new code and try again."
msgstr ""
@ -46574,9 +46589,6 @@ msgstr ""
msgid "There was a problem updating the keep latest artifacts setting."
msgstr ""
msgid "There was a problem with the credit card details you entered. Use a different credit card and try again."
msgstr ""
msgid "There was an error creating the dashboard, branch name is invalid."
msgstr ""

View File

@ -56,7 +56,7 @@
"@gitlab/cluster-client": "^1.2.0",
"@gitlab/favicon-overlay": "2.0.0",
"@gitlab/fonts": "^1.3.0",
"@gitlab/svgs": "3.54.0",
"@gitlab/svgs": "3.55.0",
"@gitlab/ui": "64.19.0",
"@gitlab/visual-review-tools": "1.7.3",
"@gitlab/web-ide": "0.0.1-dev-20230620122149",

View File

@ -12,7 +12,7 @@ module RuboCop
METHOD_NAME_PATTERN = /\A([a-z_]+_)?namespace_project(?:_[a-z_]+)?_(?:url|path)\z/.freeze
def on_send(node)
return unless method_name(node).to_s =~ METHOD_NAME_PATTERN
return unless METHOD_NAME_PATTERN.match?(method_name(node).to_s)
namespace_expr, project_expr = arguments(node)
return unless namespace_expr && project_expr

View File

@ -27,7 +27,7 @@ module RuboCop
return if in_qa_file?(node)
return unless in_spec?(node)
add_offense(node, message: MESSAGE % node.value) if SELECTORS =~ node.value
add_offense(node, message: MESSAGE % node.value) if SELECTORS.match?(node.value)
rescue StandardError
# catch all errors and ignore them.
# without this catch-all rescue, rubocop will fail

View File

@ -69,7 +69,7 @@ export const mockFrequentGroups = [
},
];
export const mockSearchedGroups = [mockRawGroup];
export const mockSearchedGroups = { data: [mockRawGroup] };
export const mockProcessedSearchedGroups = [mockGroup];
export const mockProject = {

View File

@ -10,6 +10,14 @@ jest.mock('~/api/groups_api');
const group1 = { id: 1, full_name: 'Group One', avatar_url: 'test' };
const group2 = { id: 2, full_name: 'Group Two', avatar_url: 'test' };
const allGroups = [group1, group2];
const headers = {
'X-Next-Page': 2,
'X-Page': 1,
'X-Per-Page': 20,
'X-Prev-Page': '',
'X-Total': 40,
'X-Total-Pages': 2,
};
describe('GroupSelect', () => {
let wrapper;
@ -25,7 +33,7 @@ describe('GroupSelect', () => {
};
beforeEach(() => {
getGroups.mockResolvedValueOnce(allGroups);
getGroups.mockResolvedValueOnce({ data: allGroups, headers });
});
const findListbox = () => wrapper.findComponent(GlCollapsibleListbox);
@ -121,4 +129,60 @@ describe('GroupSelect', () => {
expect(findListboxToggle().text()).toBe(group1.full_name);
});
});
describe('infinite scroll', () => {
it('sets infinite scroll related props', async () => {
createComponent();
await waitForPromises();
expect(findListbox().props()).toMatchObject({
infiniteScroll: true,
infiniteScrollLoading: false,
totalItems: 40,
});
});
describe('when `bottom-reached` event is fired', () => {
it('indicates new groups are loading and adds them to the listbox', async () => {
createComponent();
await waitForPromises();
const infiniteScrollGroup = {
id: 3,
full_name: 'Infinite scroll group',
avatar_url: 'test',
};
getGroups.mockResolvedValueOnce({ data: [infiniteScrollGroup], headers });
findListbox().vm.$emit('bottom-reached');
await nextTick();
expect(findListbox().props('infiniteScrollLoading')).toBe(true);
await waitForPromises();
expect(findListbox().props('items')[2]).toMatchObject({
value: infiniteScrollGroup.id,
id: infiniteScrollGroup.id,
name: infiniteScrollGroup.full_name,
avatarUrl: infiniteScrollGroup.avatar_url,
});
});
describe('when API request fails', () => {
it('emits `error` event', async () => {
createComponent();
await waitForPromises();
getGroups.mockRejectedValueOnce();
findListbox().vm.$emit('bottom-reached');
await waitForPromises();
expect(wrapper.emitted('error')).toEqual([[GroupSelect.i18n.errorMessage]]);
});
});
});
});
});

View File

@ -1,4 +1,4 @@
import { GlModal, GlSprintf } from '@gitlab/ui';
import { GlModal, GlSprintf, GlAlert } from '@gitlab/ui';
import { nextTick } from 'vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import Api from '~/api';
@ -250,4 +250,15 @@ describe('InviteGroupsModal', () => {
});
});
});
describe('when group select emits an error event', () => {
it('displays error alert', async () => {
createComponent();
findGroupSelect().vm.$emit('error', GroupSelect.i18n.errorMessage);
await nextTick();
expect(wrapper.findComponent(GlAlert).text()).toBe(GroupSelect.i18n.errorMessage);
});
});
});

View File

@ -1,4 +1,9 @@
import { GlDropdown, GlDropdownItem, GlSprintf } from '@gitlab/ui';
import {
GlDisclosureDropdown,
GlDisclosureDropdownItem,
GlDisclosureDropdownGroup,
GlSprintf,
} from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import PipelineArtifacts from '~/pipelines/components/pipelines_list/pipelines_artifacts.vue';
@ -25,25 +30,27 @@ describe('Pipelines Artifacts dropdown', () => {
},
stubs: {
GlSprintf,
GlDisclosureDropdown,
GlDisclosureDropdownItem,
GlDisclosureDropdownGroup,
},
});
};
const findDropdown = () => wrapper.findComponent(GlDropdown);
const findFirstGlDropdownItem = () => wrapper.findComponent(GlDropdownItem);
const findAllGlDropdownItems = () =>
wrapper.findComponent(GlDropdown).findAllComponents(GlDropdownItem);
const findGlDropdown = () => wrapper.findComponent(GlDisclosureDropdown);
const findFirstGlDropdownItem = () => wrapper.findComponent(GlDisclosureDropdownItem);
it('should render a dropdown with all the provided artifacts', () => {
createComponent();
expect(findAllGlDropdownItems()).toHaveLength(artifacts.length);
const [{ items }] = findGlDropdown().props('items');
expect(items).toHaveLength(artifacts.length);
});
it('should render a link with the provided path', () => {
createComponent();
expect(findFirstGlDropdownItem().attributes('href')).toBe(artifacts[0].path);
expect(findFirstGlDropdownItem().props('item').href).toBe(artifacts[0].path);
expect(findFirstGlDropdownItem().text()).toBe(artifacts[0].name);
});
@ -51,7 +58,7 @@ describe('Pipelines Artifacts dropdown', () => {
it('should not render the dropdown', () => {
createComponent({ mockArtifacts: [] });
expect(findDropdown().exists()).toBe(false);
expect(findGlDropdown().exists()).toBe(false);
});
});
});

View File

@ -5,10 +5,11 @@ import {
GlSkeletonLoader,
GlButton,
GlEmptyState,
GlIntersectionObserver,
} from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { isLoggedIn } from '~/lib/utils/common_utils';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
@ -67,15 +68,20 @@ describe('WorkItemDetail component', () => {
const findCreatedUpdated = () => wrapper.findComponent(WorkItemCreatedUpdated);
const findWorkItemDescription = () => wrapper.findComponent(WorkItemDescription);
const findWorkItemAttributesWrapper = () => wrapper.findComponent(WorkItemAttributesWrapper);
const findParent = () => wrapper.find('[data-testid="work-item-parent"]');
const findParent = () => wrapper.findByTestId('work-item-parent');
const findParentButton = () => findParent().findComponent(GlButton);
const findCloseButton = () => wrapper.find('[data-testid="work-item-close"]');
const findWorkItemType = () => wrapper.find('[data-testid="work-item-type"]');
const findCloseButton = () => wrapper.findByTestId('work-item-close');
const findWorkItemType = () => wrapper.findByTestId('work-item-type');
const findHierarchyTree = () => wrapper.findComponent(WorkItemTree);
const findNotesWidget = () => wrapper.findComponent(WorkItemNotes);
const findModal = () => wrapper.findComponent(WorkItemDetailModal);
const findAbuseCategorySelector = () => wrapper.findComponent(AbuseCategorySelector);
const findWorkItemTodos = () => wrapper.findComponent(WorkItemTodos);
const findIntersectionObserver = () => wrapper.findComponent(GlIntersectionObserver);
const findStickyHeader = () => wrapper.findByTestId('work-item-sticky-header');
const findWorkItemTwoColumnViewContainer = () => wrapper.findByTestId('work-item-overview');
const findRightSidebar = () => wrapper.findByTestId('work-item-overview-right-sidebar');
const triggerPageScroll = () => findIntersectionObserver().vm.$emit('disappear');
const createComponent = ({
isModal = false,
@ -92,7 +98,7 @@ describe('WorkItemDetail component', () => {
confidentialityMock,
];
wrapper = shallowMount(WorkItemDetail, {
wrapper = shallowMountExtended(WorkItemDetail, {
apolloProvider: createMockApollo(handlers),
isLoggedIn: isLoggedIn(),
propsData: {
@ -646,4 +652,56 @@ describe('WorkItemDetail component', () => {
expect(findAlert().text()).toBe(updateError);
});
});
describe('work item two column view', () => {
describe('when `workItemsMvc2Enabled` is false', () => {
beforeEach(async () => {
createComponent({ workItemsMvc2Enabled: false });
await waitForPromises();
});
it('does not have the `work-item-overview` class', () => {
expect(findWorkItemTwoColumnViewContainer().classes()).not.toContain('work-item-overview');
});
it('does not have sticky header', () => {
expect(findIntersectionObserver().exists()).toBe(false);
expect(findStickyHeader().exists()).toBe(false);
});
it('does not have right sidebar', () => {
expect(findRightSidebar().exists()).toBe(false);
});
});
describe('when `workItemsMvc2Enabled` is true', () => {
beforeEach(async () => {
createComponent({ workItemsMvc2Enabled: true });
await waitForPromises();
});
it('has the `work-item-overview` class', () => {
expect(findWorkItemTwoColumnViewContainer().classes()).toContain('work-item-overview');
});
it('does not show sticky header by default', () => {
expect(findStickyHeader().exists()).toBe(false);
});
it('has the sticky header when the page is scrolled', async () => {
expect(findIntersectionObserver().exists()).toBe(true);
global.pageYOffset = 100;
triggerPageScroll();
await nextTick();
expect(findStickyHeader().exists()).toBe(true);
});
it('has the right sidebar', () => {
expect(findRightSidebar().exists()).toBe(true);
});
});
});
});

View File

@ -98,7 +98,7 @@ RSpec.describe Gitlab::Cluster::Mixins::PumaCluster do
loop do
line = process.readline
puts "PUMA_DEBUG: #{line}" if ENV['PUMA_DEBUG']
break if line =~ output
break if line.match?(output)
end
end
end

View File

@ -1173,7 +1173,50 @@ RSpec.describe Gitlab::Git::Repository, feature_category: :source_code_managemen
commit_result.newrev
end
subject { repository.new_blobs(newrevs).to_a }
subject { repository.new_blobs(newrevs) }
describe 'memoization' do
context 'when the fix_new_blobs_memoization feature flag is disabled' do
before do
stub_feature_flags(fix_new_blobs_memoization: false)
end
context 'when called with different revisions' do
it 'calls blobs with the same arguments and memoizes the result' do # for documenting bug behaviour
expect(repository).to receive(:blobs).twice.with(["--not", "--all", "--not", "revision1"], kind_of(Hash))
.and_return(['first_result'], ['second_result'])
expect(repository.new_blobs(['revision1'])).to eq(['first_result'])
expect(repository.new_blobs(['revision2'])).to eq(['second_result'])
expect(repository.new_blobs(['revision1'])).to eq(['first_result'])
expect(repository.new_blobs(['revision2'])).to eq(['second_result'])
end
end
end
context 'when the fix_new_blobs_memoization feature flag is enabled' do
before do
allow(repository).to receive(:blobs).once.with(["--not", "--all", "--not", "revision1"], kind_of(Hash))
.and_return(['first result'])
repository.new_blobs(['revision1'])
end
it 'calls blobs only once' do
expect(repository.new_blobs(['revision1'])).to eq(['first result'])
end
context 'when called with a different revision' do
before do
allow(repository).to receive(:blobs).once.with(["--not", "--all", "--not", "revision2"], kind_of(Hash))
.and_return(['second result'])
repository.new_blobs(['revision2'])
end
it 'memoizes the different arguments' do
expect(repository.new_blobs(['revision2'])).to eq(['second result'])
end
end
end
end
shared_examples '#new_blobs with revisions' do
before do
@ -1195,7 +1238,9 @@ RSpec.describe Gitlab::Git::Repository, feature_category: :source_code_managemen
it 'memoizes results' do
expect(subject).to match_array(expected_blobs)
expect(subject).to match_array(expected_blobs)
# call subject again
expect(repository.new_blobs(newrevs)).to match_array(expected_blobs)
end
end

View File

@ -156,14 +156,6 @@ RSpec.describe Gitlab::Pagination::Keyset::InOperatorOptimization::QueryBuilder
let(:batch_size) { 1 }
it_behaves_like 'correct ordering examples'
context 'when key_set_optimizer_ignored_columns feature flag is disabled' do
before do
stub_feature_flags(key_set_optimizer_ignored_columns: false)
end
it_behaves_like 'correct ordering examples'
end
end
context 'when iterating records with LIMIT 3' do

View File

@ -83,16 +83,6 @@ RSpec.describe Gitlab::Pagination::Keyset::InOperatorOptimization::Strategies::R
model.default_select_columns.map { |column| "(#{described_class::RECORDS_COLUMN}).#{column.name}" }
)
end
context 'when the key_set_optimizer_ignored_columns feature flag is disabled' do
before do
stub_feature_flags(key_set_optimizer_ignored_columns: false)
end
it 'does not specify the selected column names' do
expect(strategy.final_projections).to contain_exactly("(#{described_class::RECORDS_COLUMN}).*")
end
end
end
end
end

View File

@ -702,16 +702,6 @@ RSpec.describe Gitlab::Pagination::Keyset::Order do
end
end
context 'when key_set_optimizer_ignored_columns feature flag is disabled' do
before do
stub_feature_flags(key_set_optimizer_ignored_columns: false)
end
it 'returns items in the correct order' do
expect(items).to eq(expected_results)
end
end
it 'returns items in the correct order' do
expect(items).to eq(expected_results)
end

View File

@ -80,7 +80,7 @@ RSpec.describe Emails::InProductMarketing do
is_expected.to have_body_text(message.subtitle)
is_expected.to have_body_text(CGI.unescapeHTML(message.cta_link))
if track =~ /(create|verify)/
if /create|verify/.match?(track)
is_expected.to have_body_text(message.invite_text)
is_expected.to have_body_text(CGI.unescapeHTML(message.invite_link))
else

View File

@ -152,7 +152,7 @@ RSpec.configure do |config|
# Admin controller specs get auto admin mode enabled since they are
# protected by the 'EnforcesAdminAuthentication' concern
metadata[:enable_admin_mode] = true if location =~ %r{(ee)?/spec/controllers/admin/}
metadata[:enable_admin_mode] = true if %r{(ee)?/spec/controllers/admin/}.match?(location)
end
config.define_derived_metadata(file_path: %r{(ee)?/spec/.+_docs\.rb\z}) do |metadata|

View File

@ -5,6 +5,7 @@ require 'capybara/rails'
require 'capybara/rspec'
require 'capybara-screenshot/rspec'
require 'selenium-webdriver'
require 'gitlab/utils/all'
# Give CI some extra time
timeout = ENV['CI'] || ENV['CI_SERVER'] ? 30 : 10
@ -117,7 +118,7 @@ Capybara.register_driver :firefox do |app|
options.add_argument("--window-size=#{CAPYBARA_WINDOW_SIZE.join(',')}")
# Run headless by default unless WEBDRIVER_HEADLESS specified
options.add_argument("--headless") unless ENV['WEBDRIVER_HEADLESS'] =~ /^(false|no|0)$/i
options.add_argument("--headless") unless Gitlab::Utils.to_boolean(ENV['WEBDRIVER_HEADLESS'], default: false)
Capybara::Selenium::Driver.new(
app,

View File

@ -523,7 +523,7 @@ module TestEnv
def component_matches_git_sha?(component_folder, expected_version)
# Not a git SHA, so return early
return false unless expected_version =~ ::Gitlab::Git::COMMIT_ID
return false unless ::Gitlab::Git::COMMIT_ID.match?(expected_version)
return false unless Dir.exist?(component_folder)

View File

@ -56,7 +56,7 @@ RSpec.shared_context 'with integration' do
hash.merge!(k => 'key:value')
elsif integration == 'packagist' && k == :server
hash.merge!(k => 'https://packagist.example.com')
elsif k =~ /^(.*_url|url|webhook)/
elsif /^(.*_url|url|webhook)/.match?(k)
hash.merge!(k => "http://example.com")
elsif integration_klass.method_defined?("#{k}?")
hash.merge!(k => true)

View File

@ -284,7 +284,7 @@ RSpec.shared_examples 'thread comments for issue, epic and merge request' do |re
expect(new_comment).to have_css('.discussion-with-resolve-btn')
end
if resource_name =~ /(issue|merge request)/
if /(issue|merge request)/.match?(resource_name)
it 'can be replied to' do
submit_reply('some text')
@ -373,7 +373,7 @@ RSpec.shared_examples 'thread comments for issue, epic and merge request' do |re
expect(page).not_to have_selector menu_selector
end
if resource_name =~ /(issue|merge request)/
if /(issue|merge request)/.match?(resource_name)
it 'updates the close button text' do
expect(find(close_selector)).to have_content "Comment & close #{resource_name}"
end
@ -402,7 +402,7 @@ RSpec.shared_examples 'thread comments for issue, epic and merge request' do |re
end
end
if resource_name =~ /(issue|merge request)/
if /(issue|merge request)/.match?(resource_name)
describe "on a closed #{resource_name}" do
before do
find("#{form_selector} .js-note-target-close").click

View File

@ -65,6 +65,11 @@ RSpec.describe Tooling::Danger::ProjectHelper do
'config/foo.js' | [:frontend]
'config/deep/foo.js' | [:frontend]
'app/components/pajamas/empty_state_component.html.haml' | [:frontend, :backend]
'ee/app/components/pajamas/empty_state_component.html.haml' | [:frontend, :backend]
'app/components/diffs/overflow_warning_component.html.haml' | [:frontend, :backend]
'app/components/layouts/horizontal_section_component.rb' | [:frontend, :backend]
'ee/app/assets/foo' | [:frontend]
'ee/app/views/foo' | [:frontend, :backend]
'ee/spec/frontend/bar' | [:frontend]
@ -112,7 +117,7 @@ RSpec.describe Tooling::Danger::ProjectHelper do
'scripts/glfm/bar.rb' | [:backend]
'scripts/glfm/bar.js' | [:frontend]
'scripts/remote_development/run-smoke-test-suite.sh' | [:remote_development]
'scripts/remote_development/run-smoke-test-suite.sh' | [:remote_development_be]
'scripts/lib/glfm/bar.rb' | [:backend]
'scripts/lib/glfm/bar.js' | [:frontend]
'scripts/bar.rb' | [:backend, :tooling]

View File

@ -238,7 +238,7 @@ RSpec.describe Quality::TestLevel, feature_category: :tooling do
it 'ensures all spec/ folders are covered by a test level' do
Dir['{,ee/}spec/**/*/'].each do |path|
next if path =~ %r{\A(ee/)?spec/(benchmarks|docs_screenshots|fixtures|frontend_integration|support)/}
next if %r{\A(ee/)?spec/(benchmarks|docs_screenshots|fixtures|frontend_integration|support)/}.match?(path)
expect { subject.level_for(path) }.not_to raise_error
end

View File

@ -77,7 +77,7 @@ module Tooling
def metric_scope_affected
select_models(helper.modified_files).each_with_object(Hash.new { |h, k| h[k] = [] }) do |file_name, matched_files|
helper.changed_lines(file_name).each do |mod_line, _i|
next unless mod_line =~ /^\+\s+scope :\w+/
next unless /^\+\s+scope :\w+/.match?(mod_line)
affected_scope = mod_line.match(/:\w+/)
next if affected_scope.nil?

View File

@ -14,7 +14,7 @@ module Tooling
def database_dictionary_files(change_type:)
files = helper.public_send("#{change_type}_files") # rubocop:disable GitlabSecurity/PublicSend
files.filter_map { |path| Found.new(path) if path =~ DICTIONARY_PATH_REGEXP }
files.filter_map { |path| Found.new(path) if DICTIONARY_PATH_REGEXP.match?(path) }
end
class Found

View File

@ -70,6 +70,7 @@ module Tooling
%r{\A((ee|jh)/)?app/assets/} => :frontend,
%r{\A((ee|jh)/)?app/views/.*\.svg} => :frontend,
%r{\A((ee|jh)/)?app/views/} => [:frontend, :backend],
%r{\A((ee|jh)/)?app/components/} => [:frontend, :backend],
%r{\A((ee|jh)/)?public/} => :frontend,
%r{\A((ee|jh)/)?spec/(javascripts|frontend|frontend_integration)/} => :frontend,
%r{\A((ee|jh)/)?spec/contracts/consumer} => :frontend,
@ -115,7 +116,7 @@ module Tooling
%r{\A((ee|jh)/)?scripts/(lib/)?glfm/.*\.rb} => [:backend],
%r{\A((ee|jh)/)?scripts/(lib/)?glfm/.*\.js} => [:frontend],
%r{\A((ee|jh)/)?scripts/remote_development/.*} => [:remote_development],
%r{\A((ee|jh)/)?scripts/remote_development/.*} => [:remote_development_be],
%r{\A((ee|jh)/)?scripts/.*\.rb} => [:backend, :tooling],
%r{\A((ee|jh)/)?scripts/.*\.js} => [:frontend, :tooling],
%r{\A((ee|jh)/)?scripts/} => :tooling,

View File

@ -18,7 +18,7 @@ module Tooling
changed_lines = helper.changed_lines(filename)
changed_lines.each do |changed_line|
next unless changed_line =~ RSPEC_TOP_LEVEL_DESCRIBE_REGEX
next unless RSPEC_TOP_LEVEL_DESCRIBE_REGEX.match?(changed_line)
line_number = file_lines.find_index(changed_line.delete_prefix('+'))
next unless line_number

View File

@ -1127,10 +1127,10 @@
stylelint-declaration-strict-value "1.8.0"
stylelint-scss "4.2.0"
"@gitlab/svgs@3.54.0":
version "3.54.0"
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.54.0.tgz#6002ed7b3c2db832bef34629d6d5677ac36c45d6"
integrity sha512-Fvo/0lF/Gx+na21Qg4qr02EsP1OEhVlkuh8ctmHMLu5cr5ho3b/MZYLHLjI8F5FDkTIpennyYuhxqiU8kTVM2Q==
"@gitlab/svgs@3.55.0":
version "3.55.0"
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.55.0.tgz#c67c5dddf54c400485762aff6a693e1f5a643739"
integrity sha512-1wuXRGhrWKfWXSM9ZI1aRHlZ0wv4X7tJjDil+AQVjPBANB6oBXAPAiga+qkzkBHss7TzyOjY7OytG/9L5weDLg==
"@gitlab/ui@64.19.0":
version "64.19.0"