Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-07-22 09:08:22 +00:00
parent 6eb3540d3d
commit 8e0dafbb66
101 changed files with 812 additions and 1341 deletions

View File

@ -2,7 +2,7 @@ review-cleanup:
extends:
- .default-retry
- .review:rules:review-cleanup
image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-helm3.5-kubectl1.17
image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-helm3-kubectl1.14
stage: prepare
environment:
name: review/auto-cleanup

View File

@ -178,61 +178,6 @@ Graphql/OldTypes:
- 'app/graphql/types/container_repository_type.rb'
- 'app/graphql/types/countable_connection_type.rb'
- 'app/graphql/types/custom_emoji_type.rb'
- 'app/graphql/types/design_management/design_fields.rb'
- 'app/graphql/types/design_management/version_type.rb'
- 'app/graphql/types/diff_paths_input_type.rb'
- 'app/graphql/types/diff_refs_type.rb'
- 'app/graphql/types/diff_stats_summary_type.rb'
- 'app/graphql/types/diff_stats_type.rb'
- 'app/graphql/types/environment_type.rb'
- 'app/graphql/types/error_tracking/sentry_detailed_error_type.rb'
- 'app/graphql/types/error_tracking/sentry_error_collection_type.rb'
- 'app/graphql/types/error_tracking/sentry_error_frequency_type.rb'
- 'app/graphql/types/error_tracking/sentry_error_stack_trace_context_type.rb'
- 'app/graphql/types/error_tracking/sentry_error_stack_trace_entry_type.rb'
- 'app/graphql/types/error_tracking/sentry_error_stack_trace_type.rb'
- 'app/graphql/types/error_tracking/sentry_error_tags_type.rb'
- 'app/graphql/types/error_tracking/sentry_error_type.rb'
- 'app/graphql/types/event_type.rb'
- 'app/graphql/types/evidence_type.rb'
- 'app/graphql/types/grafana_integration_type.rb'
- 'app/graphql/types/invitation_interface.rb'
- 'app/graphql/types/issue_type.rb'
- 'app/graphql/types/issues/negated_issue_filter_input_type.rb'
- 'app/graphql/types/jira_import_type.rb'
- 'app/graphql/types/jira_user_type.rb'
- 'app/graphql/types/jira_users_mapping_input_type.rb'
- 'app/graphql/types/label_type.rb'
- 'app/graphql/types/member_interface.rb'
- 'app/graphql/types/merge_request_type.rb'
- 'app/graphql/types/metadata/kas_type.rb'
- 'app/graphql/types/metadata_type.rb'
- 'app/graphql/types/metrics/dashboard_type.rb'
- 'app/graphql/types/metrics/dashboards/annotation_type.rb'
- 'app/graphql/types/milestone_stats_type.rb'
- 'app/graphql/types/milestone_type.rb'
- 'app/graphql/types/namespace/package_settings_type.rb'
- 'app/graphql/types/namespace_type.rb'
- 'app/graphql/types/notes/diff_image_position_input_type.rb'
- 'app/graphql/types/notes/diff_position_base_input_type.rb'
- 'app/graphql/types/notes/diff_position_input_type.rb'
- 'app/graphql/types/notes/diff_position_type.rb'
- 'app/graphql/types/notes/note_type.rb'
- 'app/graphql/types/notes/update_diff_image_position_input_type.rb'
- 'app/graphql/types/packages/composer/json_type.rb'
- 'app/graphql/types/packages/composer/metadatum_type.rb'
- 'app/graphql/types/packages/conan/file_metadatum_type.rb'
- 'app/graphql/types/packages/conan/metadatum_type.rb'
- 'app/graphql/types/packages/maven/metadatum_type.rb'
- 'app/graphql/types/packages/nuget/metadatum_type.rb'
- 'app/graphql/types/packages/package_file_type.rb'
- 'app/graphql/types/packages/package_tag_type.rb'
- 'app/graphql/types/packages/package_type.rb'
- 'app/graphql/types/packages/pypi/metadatum_type.rb'
- 'app/graphql/types/project_type.rb'
- 'app/graphql/types/projects/service_type.rb'
- 'app/graphql/types/projects/services/jira_project_type.rb'
- 'app/graphql/types/prometheus_alert_type.rb'
- 'app/graphql/types/query_complexity_type.rb'
- 'app/graphql/types/release_asset_link_shared_input_arguments.rb'
- 'app/graphql/types/release_asset_link_type.rb'

View File

@ -36,6 +36,34 @@ const loadRichBlobViewer = (type) => {
}
};
const loadViewer = (viewerParam) => {
const viewer = viewerParam;
const url = viewer.getAttribute('data-url');
if (!url || viewer.getAttribute('data-loaded') || viewer.getAttribute('data-loading')) {
return Promise.resolve(viewer);
}
viewer.setAttribute('data-loading', 'true');
return axios.get(url).then(({ data }) => {
viewer.innerHTML = data.html;
window.requestIdleCallback(() => {
viewer.removeAttribute('data-loading');
});
return viewer;
});
};
export const initAuxiliaryViewer = () => {
const auxiliaryViewer = document.querySelector('.blob-viewer[data-type="auxiliary"]');
if (!auxiliaryViewer) return;
loadViewer(auxiliaryViewer);
};
export const handleBlobRichViewer = (viewer, type) => {
if (!viewer || !type) return;
@ -49,27 +77,20 @@ export const handleBlobRichViewer = (viewer, type) => {
});
};
export default class BlobViewer {
export class BlobViewer {
constructor() {
performanceMarkAndMeasure({
mark: REPO_BLOB_LOAD_VIEWER_START,
});
const viewer = document.querySelector('.blob-viewer[data-type="rich"]');
const type = viewer?.dataset?.richType;
BlobViewer.initAuxiliaryViewer();
initAuxiliaryViewer();
handleBlobRichViewer(viewer, type);
this.initMainViewers();
}
static initAuxiliaryViewer() {
const auxiliaryViewer = document.querySelector('.blob-viewer[data-type="auxiliary"]');
if (!auxiliaryViewer) return;
BlobViewer.loadViewer(auxiliaryViewer);
}
initMainViewers() {
this.$fileHolder = $('.file-holder');
if (!this.$fileHolder.length) return;
@ -173,7 +194,7 @@ export default class BlobViewer {
this.activeViewer = newViewer;
this.toggleCopyButtonState();
BlobViewer.loadViewer(newViewer)
loadViewer(newViewer)
.then((viewer) => {
$(viewer).renderGFM();
window.requestIdleCallback(() => {
@ -205,25 +226,4 @@ export default class BlobViewer {
}),
);
}
static loadViewer(viewerParam) {
const viewer = viewerParam;
const url = viewer.getAttribute('data-url');
if (!url || viewer.getAttribute('data-loaded') || viewer.getAttribute('data-loading')) {
return Promise.resolve(viewer);
}
viewer.setAttribute('data-loading', 'true');
return axios.get(url).then(({ data }) => {
viewer.innerHTML = data.html;
window.requestIdleCallback(() => {
viewer.removeAttribute('data-loading');
});
return viewer;
});
}
}

View File

@ -1,56 +0,0 @@
<script>
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
import limitWarning from './limit_warning_component.vue';
import totalTime from './total_time_component.vue';
export default {
components: {
userAvatarImage,
limitWarning,
totalTime,
},
props: {
items: {
type: Array,
default: () => [],
required: false,
},
stage: {
type: Object,
default: () => ({}),
required: false,
},
},
};
</script>
<template>
<div>
<div class="events-description">
{{ stage.description }}
<limit-warning :count="items.length" />
</div>
<ul class="stage-event-list">
<li v-for="(mergeRequest, i) in items" :key="i" class="stage-event-item">
<div class="item-details">
<!-- FIXME: Pass an alt attribute here for accessibility -->
<user-avatar-image :img-src="mergeRequest.author.avatarUrl" />
<h5 class="item-title merge-request-title">
<a :href="mergeRequest.url"> {{ mergeRequest.title }} </a>
</h5>
<a :href="mergeRequest.url" class="issue-link"> !{{ mergeRequest.iid }} </a> &middot;
<span>
{{ s__('OpenedNDaysAgo|Opened') }}
<a :href="mergeRequest.url" class="issue-date"> {{ mergeRequest.createdAt }} </a>
</span>
<span>
{{ s__('ByAuthor|by') }}
<a :href="mergeRequest.author.webUrl" class="issue-author-link">
{{ mergeRequest.author.name }}
</a>
</span>
</div>
<div class="item-time"><total-time :time="mergeRequest.totalTime" /></div>
</li>
</ul>
</div>
</template>

View File

@ -1,54 +0,0 @@
<script>
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
import limitWarning from './limit_warning_component.vue';
import totalTime from './total_time_component.vue';
export default {
components: {
userAvatarImage,
limitWarning,
totalTime,
},
props: {
items: {
type: Array,
default: () => [],
required: false,
},
stage: {
type: Object,
default: () => ({}),
required: false,
},
},
};
</script>
<template>
<div>
<div class="events-description">
{{ stage.description }}
<limit-warning :count="items.length" />
</div>
<ul class="stage-event-list">
<li v-for="(issue, i) in items" :key="i" class="stage-event-item">
<div class="item-details">
<!-- FIXME: Pass an alt attribute here for accessibility -->
<user-avatar-image :img-src="issue.author.avatarUrl" />
<h5 class="item-title issue-title">
<a :href="issue.url" class="issue-title"> {{ issue.title }} </a>
</h5>
<a :href="issue.url" class="issue-link">#{{ issue.iid }}</a> &middot;
<span>
{{ s__('OpenedNDaysAgo|Opened') }}
<a :href="issue.url" class="issue-date">{{ issue.createdAt }}</a>
</span>
<span>
{{ s__('ByAuthor|by') }}
<a :href="issue.author.webUrl" class="issue-author-link"> {{ issue.author.name }} </a>
</span>
</div>
<div class="item-time"><total-time :time="issue.totalTime" /></div>
</li>
</ul>
</div>
</template>

View File

@ -1,60 +0,0 @@
<script>
export default {
name: 'StageNavItem',
props: {
isDefaultStage: {
type: Boolean,
default: false,
required: false,
},
isActive: {
type: Boolean,
default: false,
required: false,
},
isUserAllowed: {
type: Boolean,
required: true,
},
title: {
type: String,
required: true,
},
value: {
type: String,
default: '',
required: false,
},
},
computed: {
hasValue() {
return this.value && this.value.length > 0;
},
},
};
</script>
<template>
<li @click="$emit('select')">
<div
:class="{ active: isActive }"
class="stage-nav-item d-flex pl-4 pr-4 m-0 mb-1 ml-2 rounded border-color-default border-style-solid border-width-1px"
>
<div
class="stage-nav-item-cell stage-name w-50 pr-2"
:class="{ 'font-weight-bold': isActive }"
>
{{ title }}
</div>
<div class="stage-nav-item-cell stage-median w-50">
<template v-if="isUserAllowed">
<span v-if="hasValue">{{ value }}</span>
<span v-else class="stage-empty">{{ __('Not enough data') }}</span>
</template>
<template v-else>
<span class="not-available">{{ __('Not available') }}</span>
</template>
</div>
</div>
</li>
</template>

View File

@ -1,70 +0,0 @@
<script>
import { GlIcon } from '@gitlab/ui';
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
import limitWarning from './limit_warning_component.vue';
import totalTime from './total_time_component.vue';
export default {
components: {
userAvatarImage,
totalTime,
limitWarning,
GlIcon,
},
props: {
items: {
type: Array,
default: () => [],
required: false,
},
stage: {
type: Object,
default: () => ({}),
required: false,
},
},
};
</script>
<template>
<div>
<div class="events-description">
{{ stage.description }}
<limit-warning :count="items.length" />
</div>
<ul class="stage-event-list">
<li v-for="(mergeRequest, i) in items" :key="i" class="stage-event-item">
<div class="item-details">
<!-- FIXME: Pass an alt attribute here for accessibility -->
<user-avatar-image :img-src="mergeRequest.author.avatarUrl" />
<h5 class="item-title merge-request-title">
<a :href="mergeRequest.url"> {{ mergeRequest.title }} </a>
</h5>
<a :href="mergeRequest.url" class="issue-link">!{{ mergeRequest.iid }}</a> &middot;
<span>
{{ s__('OpenedNDaysAgo|Opened') }}
<a :href="mergeRequest.url" class="issue-date">{{ mergeRequest.createdAt }}</a>
</span>
<span>
{{ s__('ByAuthor|by') }}
<a :href="mergeRequest.author.webUrl" class="issue-author-link">{{
mergeRequest.author.name
}}</a>
</span>
<template v-if="mergeRequest.state === 'closed'">
<span class="merge-request-state">
<gl-icon name="cancel" class="gl-vertical-align-text-bottom" />
{{ __('CLOSED') }}
</span>
</template>
<template v-else>
<span v-if="mergeRequest.branch" class="merge-request-branch">
<gl-icon :size="16" name="fork" />
<a :href="mergeRequest.branch.url"> {{ mergeRequest.branch.name }} </a>
</span>
</template>
</div>
<div class="item-time"><total-time :time="mergeRequest.totalTime" /></div>
</li>
</ul>
</div>
</template>

View File

@ -1,60 +0,0 @@
<script>
import { GlIcon, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
import limitWarning from './limit_warning_component.vue';
import totalTime from './total_time_component.vue';
export default {
components: {
userAvatarImage,
totalTime,
limitWarning,
GlIcon,
},
directives: {
SafeHtml,
},
props: {
items: {
type: Array,
default: () => [],
required: false,
},
stage: {
type: Object,
default: () => ({}),
required: false,
},
},
};
</script>
<template>
<div>
<div class="events-description">
{{ stage.description }}
<limit-warning :count="items.length" />
</div>
<ul class="stage-event-list">
<li v-for="(build, i) in items" :key="i" class="stage-event-item item-build-component">
<div class="item-details">
<!-- FIXME: Pass an alt attribute here for accessibility -->
<user-avatar-image :img-src="build.author.avatarUrl" />
<h5 class="item-title">
<a :href="build.url" class="pipeline-id"> #{{ build.id }} </a>
<gl-icon :size="16" name="fork" />
<a :href="build.branch.url" class="ref-name"> {{ build.branch.name }} </a>
<span class="icon-branch gl-text-gray-400">
<gl-icon name="commit" :size="14" />
</span>
<a :href="build.commitUrl" class="commit-sha"> {{ build.shortSha }} </a>
</h5>
<span>
<a :href="build.url" class="build-date"> {{ build.date }} </a> {{ s__('ByAuthor|by') }}
<a :href="build.author.webUrl" class="issue-author-link"> {{ build.author.name }} </a>
</span>
</div>
<div class="item-time"><total-time :time="build.totalTime" /></div>
</li>
</ul>
</div>
</template>

View File

@ -1,56 +0,0 @@
<script>
import { GlIcon } from '@gitlab/ui';
import limitWarning from './limit_warning_component.vue';
import totalTime from './total_time_component.vue';
export default {
components: {
totalTime,
limitWarning,
GlIcon,
},
props: {
items: {
type: Array,
default: () => [],
required: false,
},
stage: {
type: Object,
default: () => ({}),
required: false,
},
},
};
</script>
<template>
<div>
<div class="events-description">
{{ stage.description }}
<limit-warning :count="items.length" />
</div>
<ul class="stage-event-list">
<li v-for="(build, i) in items" :key="i" class="stage-event-item item-build-component">
<div class="item-details">
<h5 class="item-title">
<span class="icon-build-status gl-text-green-500">
<gl-icon name="status_success" :size="14" />
</span>
<a :href="build.url" class="item-build-name"> {{ build.name }} </a> &middot;
<a :href="build.url" class="pipeline-id"> #{{ build.id }} </a>
<gl-icon :size="16" name="fork" />
<a :href="build.branch.url" class="ref-name"> {{ build.branch.name }} </a>
<span class="icon-branch gl-text-gray-400">
<gl-icon name="commit" :size="14" />
</span>
<a :href="build.commitUrl" class="commit-sha"> {{ build.shortSha }} </a>
</h5>
<span>
<a :href="build.url" class="issue-date"> {{ build.date }} </a>
</span>
</div>
<div class="item-time"><total-time :time="build.totalTime" /></div>
</li>
</ul>
</div>
</template>

View File

@ -1,98 +0,0 @@
export default {
issue: {
created_at: '',
url: '',
iid: '',
title: '',
total_time: {},
author: {
avatar_url: '',
id: '',
name: '',
web_url: '',
},
},
plan: {
title: '',
commit_url: '',
short_sha: '',
total_time: {},
author: {
name: '',
id: '',
avatar_url: '',
web_url: '',
},
},
code: {
title: '',
iid: '',
created_at: '',
url: '',
total_time: {},
author: {
name: '',
id: '',
avatar_url: '',
web_url: '',
},
},
test: {
name: '',
id: '',
date: '',
url: '',
short_sha: '',
commit_url: '',
total_time: {},
branch: {
name: '',
url: '',
},
},
review: {
title: '',
iid: '',
created_at: '',
url: '',
state: '',
total_time: {},
author: {
name: '',
id: '',
avatar_url: '',
web_url: '',
},
},
staging: {
id: '',
short_sha: '',
date: '',
url: '',
commit_url: '',
total_time: {},
author: {
name: '',
id: '',
avatar_url: '',
web_url: '',
},
branch: {
name: '',
url: '',
},
},
production: {
title: '',
created_at: '',
url: '',
iid: '',
total_time: {},
author: {
name: '',
id: '',
avatar_url: '',
web_url: '',
},
},
};

View File

@ -1,11 +1,6 @@
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { DEFAULT_DAYS_TO_DISPLAY } from '../constants';
import {
decorateData,
decorateEvents,
formatMedianValues,
calculateFormattedDayInPast,
} from '../utils';
import { decorateData, formatMedianValues, calculateFormattedDayInPast } from '../utils';
import * as types from './mutation_types';
export default {
@ -82,10 +77,11 @@ export default {
state.hasError = false;
},
[types.RECEIVE_STAGE_DATA_SUCCESS](state, { events = [] }) {
const { selectedStage } = state;
state.isLoadingStage = false;
state.isEmptyStage = !events.length;
state.selectedStageEvents = decorateEvents(events, selectedStage);
state.selectedStageEvents = events.map((ev) =>
convertObjectPropsToCamelCase(ev, { deep: true }),
);
state.hasError = false;
},
[types.RECEIVE_STAGE_DATA_ERROR](state, error) {

View File

@ -2,27 +2,10 @@ import dateFormat from 'dateformat';
import { unescape } from 'lodash';
import { dateFormats } from '~/analytics/shared/constants';
import { sanitize } from '~/lib/dompurify';
import { roundToNearestHalf, convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { roundToNearestHalf } from '~/lib/utils/common_utils';
import { getDateInPast } from '~/lib/utils/datetime/date_calculation_utility';
import { parseSeconds } from '~/lib/utils/datetime_utility';
import { s__, sprintf } from '../locale';
import DEFAULT_EVENT_OBJECTS from './default_event_objects';
/**
* These `decorate` methods will be removed when me migrate to the
* new table layout https://gitlab.com/gitlab-org/gitlab/-/issues/326704
*/
const mapToEvent = (event, stage) => {
return convertObjectPropsToCamelCase(
{
...DEFAULT_EVENT_OBJECTS[stage.slug],
...event,
},
{ deep: true },
);
};
export const decorateEvents = (events, stage) => events.map((event) => mapToEvent(event, stage));
const mapToSummary = ({ value, ...rest }) => ({ ...rest, value: value || '-' });
const mapToMedians = ({ name: id, value }) => ({ id, value });

View File

@ -1,5 +1,5 @@
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import BlobViewer from '~/blob/viewer/index';
import { BlobViewer } from '~/blob/viewer/index';
new ShortcutsNavigation(); // eslint-disable-line no-new
new BlobViewer(); // eslint-disable-line no-new

View File

@ -2,7 +2,7 @@ import Vue from 'vue';
import VueApollo from 'vue-apollo';
import TableOfContents from '~/blob/components/table_contents.vue';
import PipelineTourSuccessModal from '~/blob/pipeline_tour_success_modal.vue';
import BlobViewer from '~/blob/viewer/index';
import { BlobViewer } from '~/blob/viewer/index';
import GpgBadges from '~/gpg_badges';
import createDefaultClient from '~/lib/graphql';
import initBlob from '~/pages/projects/init_blob';

View File

@ -1,7 +1,7 @@
import initTree from 'ee_else_ce/repository';
import Activities from '~/activities';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import BlobViewer from '~/blob/viewer/index';
import { BlobViewer } from '~/blob/viewer/index';
import { initUploadForm } from '~/blob_edit/blob_bundle';
import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger';

View File

@ -7,13 +7,13 @@ module Types
field_class Types::BaseField
field :id, GraphQL::ID_TYPE, description: 'The ID of this design.', null: false
field :id, GraphQL::Types::ID, description: 'The ID of this design.', null: false
field :project, Types::ProjectType, null: false, description: 'The project the design belongs to.'
field :issue, Types::IssueType, null: false, description: 'The issue the design belongs to.'
field :filename, GraphQL::STRING_TYPE, null: false, description: 'The filename of the design.'
field :full_path, GraphQL::STRING_TYPE, null: false, description: 'The full path to the design file.'
field :image, GraphQL::STRING_TYPE, null: false, extras: [:parent], description: 'The URL of the full-sized image.'
field :image_v432x230, GraphQL::STRING_TYPE, null: true, extras: [:parent],
field :filename, GraphQL::Types::String, null: false, description: 'The filename of the design.'
field :full_path, GraphQL::Types::String, null: false, description: 'The full path to the design file.'
field :image, GraphQL::Types::String, null: false, extras: [:parent], description: 'The URL of the full-sized image.'
field :image_v432x230, GraphQL::Types::String, null: true, extras: [:parent],
description: 'The URL of the design resized to fit within the bounds of 432x230. ' \
'This will be `null` if the image has not been generated'
field :diff_refs, Types::DiffRefsType,
@ -26,7 +26,7 @@ module Types
extras: [:parent],
description: 'How this design was changed in the current version.'
field :notes_count,
GraphQL::INT_TYPE,
GraphQL::Types::Int,
null: false,
method: :user_notes_count,
description: 'The total count of user-created notes for this design.'

View File

@ -11,9 +11,9 @@ module Types
authorize :read_design
field :id, GraphQL::ID_TYPE, null: false,
field :id, GraphQL::Types::ID, null: false,
description: 'ID of the design version.'
field :sha, GraphQL::ID_TYPE, null: false,
field :sha, GraphQL::Types::ID, null: false,
description: 'SHA of the design version.'
field :designs,

View File

@ -2,9 +2,9 @@
module Types
class DiffPathsInputType < BaseInputObject
argument :old_path, GraphQL::STRING_TYPE, required: false,
argument :old_path, GraphQL::Types::String, required: false,
description: 'The path of the file on the start sha.'
argument :new_path, GraphQL::STRING_TYPE, required: false,
argument :new_path, GraphQL::Types::String, required: false,
description: 'The path of the file on the head sha.'
end
end

View File

@ -6,11 +6,11 @@ module Types
class DiffRefsType < BaseObject
graphql_name 'DiffRefs'
field :head_sha, GraphQL::STRING_TYPE, null: false,
field :head_sha, GraphQL::Types::String, null: false,
description: 'SHA of the HEAD at the time the comment was made.'
field :base_sha, GraphQL::STRING_TYPE, null: true,
field :base_sha, GraphQL::Types::String, null: true,
description: 'Merge base of the branch the comment was made on.'
field :start_sha, GraphQL::STRING_TYPE, null: false,
field :start_sha, GraphQL::Types::String, null: false,
description: 'SHA of the branch being compared against.'
end
# rubocop: enable Graphql/AuthorizeTypes

View File

@ -8,13 +8,13 @@ module Types
description 'Aggregated summary of changes'
field :additions, GraphQL::INT_TYPE, null: false,
field :additions, GraphQL::Types::Int, null: false,
description: 'Number of lines added.'
field :deletions, GraphQL::INT_TYPE, null: false,
field :deletions, GraphQL::Types::Int, null: false,
description: 'Number of lines deleted.'
field :changes, GraphQL::INT_TYPE, null: false,
field :changes, GraphQL::Types::Int, null: false,
description: 'Number of lines changed.'
field :file_count, GraphQL::INT_TYPE, null: false,
field :file_count, GraphQL::Types::Int, null: false,
description: 'Number of files changed.'
def changes

View File

@ -8,11 +8,11 @@ module Types
description 'Changes to a single file'
field :path, GraphQL::STRING_TYPE, null: false,
field :path, GraphQL::Types::String, null: false,
description: 'File path, relative to repository root.'
field :additions, GraphQL::INT_TYPE, null: false,
field :additions, GraphQL::Types::Int, null: false,
description: 'Number of lines added to this file.'
field :deletions, GraphQL::INT_TYPE, null: false,
field :deletions, GraphQL::Types::Int, null: false,
description: 'Number of lines deleted from this file.'
end
# rubocop: enable Graphql/AuthorizeTypes

View File

@ -9,16 +9,16 @@ module Types
authorize :read_environment
field :name, GraphQL::STRING_TYPE, null: false,
field :name, GraphQL::Types::String, null: false,
description: 'Human-readable name of the environment.'
field :id, GraphQL::ID_TYPE, null: false,
field :id, GraphQL::Types::ID, null: false,
description: 'ID of the environment.'
field :state, GraphQL::STRING_TYPE, null: false,
field :state, GraphQL::Types::String, null: false,
description: 'State of the environment, for example: available/stopped.'
field :path, GraphQL::STRING_TYPE, null: false,
field :path, GraphQL::Types::String, null: false,
description: 'The path to the environment.'
field :metrics_dashboard, Types::Metrics::DashboardType, null: true,

View File

@ -10,23 +10,23 @@ module Types
authorize :read_sentry_issue
field :id, GraphQL::ID_TYPE,
field :id, GraphQL::Types::ID,
null: false,
description: 'ID (global ID) of the error.'
field :sentry_id, GraphQL::STRING_TYPE,
field :sentry_id, GraphQL::Types::String,
method: :id,
null: false,
description: 'ID (Sentry ID) of the error.'
field :title, GraphQL::STRING_TYPE,
field :title, GraphQL::Types::String,
null: false,
description: 'Title of the error.'
field :type, GraphQL::STRING_TYPE,
field :type, GraphQL::Types::String,
null: false,
description: 'Type of the error.'
field :user_count, GraphQL::INT_TYPE,
field :user_count, GraphQL::Types::Int,
null: false,
description: 'Count of users affected by the error.'
field :count, GraphQL::INT_TYPE,
field :count, GraphQL::Types::Int,
null: false,
description: 'Count of occurrences.'
field :first_seen, Types::TimeType,
@ -35,31 +35,31 @@ module Types
field :last_seen, Types::TimeType,
null: false,
description: 'Timestamp when the error was last seen.'
field :message, GraphQL::STRING_TYPE,
field :message, GraphQL::Types::String,
null: true,
description: 'Sentry metadata message of the error.'
field :culprit, GraphQL::STRING_TYPE,
field :culprit, GraphQL::Types::String,
null: false,
description: 'Culprit of the error.'
field :external_base_url, GraphQL::STRING_TYPE,
field :external_base_url, GraphQL::Types::String,
null: false,
description: 'External Base URL of the Sentry Instance.'
field :external_url, GraphQL::STRING_TYPE,
field :external_url, GraphQL::Types::String,
null: false,
description: 'External URL of the error.'
field :sentry_project_id, GraphQL::ID_TYPE,
field :sentry_project_id, GraphQL::Types::ID,
method: :project_id,
null: false,
description: 'ID of the project (Sentry project).'
field :sentry_project_name, GraphQL::STRING_TYPE,
field :sentry_project_name, GraphQL::Types::String,
method: :project_name,
null: false,
description: 'Name of the project affected by the error.'
field :sentry_project_slug, GraphQL::STRING_TYPE,
field :sentry_project_slug, GraphQL::Types::String,
method: :project_slug,
null: false,
description: 'Slug of the project affected by the error.'
field :short_id, GraphQL::STRING_TYPE,
field :short_id, GraphQL::Types::String,
null: false,
description: 'Short ID (Sentry ID) of the error.'
field :status, Types::ErrorTracking::SentryErrorStatusEnum,
@ -68,31 +68,31 @@ module Types
field :frequency, [Types::ErrorTracking::SentryErrorFrequencyType],
null: false,
description: 'Last 24hr stats of the error.'
field :first_release_last_commit, GraphQL::STRING_TYPE,
field :first_release_last_commit, GraphQL::Types::String,
null: true,
description: 'Commit the error was first seen.'
field :last_release_last_commit, GraphQL::STRING_TYPE,
field :last_release_last_commit, GraphQL::Types::String,
null: true,
description: 'Commit the error was last seen.'
field :first_release_short_version, GraphQL::STRING_TYPE,
field :first_release_short_version, GraphQL::Types::String,
null: true,
description: 'Release short version the error was first seen.'
field :last_release_short_version, GraphQL::STRING_TYPE,
field :last_release_short_version, GraphQL::Types::String,
null: true,
description: 'Release short version the error was last seen.'
field :first_release_version, GraphQL::STRING_TYPE,
field :first_release_version, GraphQL::Types::String,
null: true,
description: 'Release version the error was first seen.'
field :last_release_version, GraphQL::STRING_TYPE,
field :last_release_version, GraphQL::Types::String,
null: true,
description: 'Release version the error was last seen.'
field :gitlab_commit, GraphQL::STRING_TYPE,
field :gitlab_commit, GraphQL::Types::String,
null: true,
description: 'GitLab commit SHA attributed to the Error based on the release version.'
field :gitlab_commit_path, GraphQL::STRING_TYPE,
field :gitlab_commit_path, GraphQL::Types::String,
null: true,
description: 'Path to the GitLab page for the GitLab commit attributed to the error.'
field :gitlab_issue_path, GraphQL::STRING_TYPE,
field :gitlab_issue_path, GraphQL::Types::String,
method: :gitlab_issue,
null: true,
description: 'URL of GitLab Issue.'

View File

@ -18,7 +18,7 @@ module Types
description: 'Stack Trace of Sentry Error.',
resolver: Resolvers::ErrorTracking::SentryErrorStackTraceResolver
field :external_url,
GraphQL::STRING_TYPE,
GraphQL::Types::String,
null: true,
description: "External URL for Sentry."
end

View File

@ -9,7 +9,7 @@ module Types
field :time, Types::TimeType,
null: false,
description: "Time the error frequency stats were recorded."
field :count, GraphQL::INT_TYPE,
field :count, GraphQL::Types::Int,
null: false,
description: "Count of errors received since the previously recorded time."
end

View File

@ -8,11 +8,11 @@ module Types
description 'An object context for a Sentry error stack trace'
field :line,
GraphQL::INT_TYPE,
GraphQL::Types::Int,
null: false,
description: 'Line number of the context.'
field :code,
GraphQL::STRING_TYPE,
GraphQL::Types::String,
null: false,
description: 'Code number of the context.'

View File

@ -7,16 +7,16 @@ module Types
graphql_name 'SentryErrorStackTraceEntry'
description 'An object containing a stack trace entry for a Sentry error'
field :function, GraphQL::STRING_TYPE,
field :function, GraphQL::Types::String,
null: true,
description: 'Function in which the Sentry error occurred.'
field :col, GraphQL::STRING_TYPE,
field :col, GraphQL::Types::String,
null: true,
description: 'Function in which the Sentry error occurred.'
field :line, GraphQL::STRING_TYPE,
field :line, GraphQL::Types::String,
null: true,
description: 'Function in which the Sentry error occurred.'
field :file_name, GraphQL::STRING_TYPE,
field :file_name, GraphQL::Types::String,
null: true,
description: 'File in which the Sentry error occurred.'
field :trace_context, [Types::ErrorTracking::SentryErrorStackTraceContextType],

View File

@ -8,10 +8,10 @@ module Types
authorize :read_sentry_issue
field :issue_id, GraphQL::STRING_TYPE,
field :issue_id, GraphQL::Types::String,
null: false,
description: 'ID of the Sentry error.'
field :date_received, GraphQL::STRING_TYPE,
field :date_received, GraphQL::Types::String,
null: false,
description: 'Time the stack trace was received by Sentry.'
field :stack_trace_entries, [Types::ErrorTracking::SentryErrorStackTraceEntryType],

View File

@ -7,10 +7,10 @@ module Types
graphql_name 'SentryErrorTags'
description 'State of a Sentry error'
field :level, GraphQL::STRING_TYPE,
field :level, GraphQL::Types::String,
null: true,
description: "Severity level of the Sentry Error."
field :logger, GraphQL::STRING_TYPE,
field :logger, GraphQL::Types::String,
null: true,
description: "Logger of the Sentry Error."
end

View File

@ -9,10 +9,10 @@ module Types
present_using SentryErrorPresenter
field :id, GraphQL::ID_TYPE,
field :id, GraphQL::Types::ID,
null: false,
description: 'ID (global ID) of the error.'
field :sentry_id, GraphQL::STRING_TYPE,
field :sentry_id, GraphQL::Types::String,
method: :id,
null: false,
description: 'ID (Sentry ID) of the error.'
@ -22,28 +22,28 @@ module Types
field :last_seen, Types::TimeType,
null: false,
description: 'Timestamp when the error was last seen.'
field :title, GraphQL::STRING_TYPE,
field :title, GraphQL::Types::String,
null: false,
description: 'Title of the error.'
field :type, GraphQL::STRING_TYPE,
field :type, GraphQL::Types::String,
null: false,
description: 'Type of the error.'
field :user_count, GraphQL::INT_TYPE,
field :user_count, GraphQL::Types::Int,
null: false,
description: 'Count of users affected by the error.'
field :count, GraphQL::INT_TYPE,
field :count, GraphQL::Types::Int,
null: false,
description: 'Count of occurrences.'
field :message, GraphQL::STRING_TYPE,
field :message, GraphQL::Types::String,
null: true,
description: 'Sentry metadata message of the error.'
field :culprit, GraphQL::STRING_TYPE,
field :culprit, GraphQL::Types::String,
null: false,
description: 'Culprit of the error.'
field :external_url, GraphQL::STRING_TYPE,
field :external_url, GraphQL::Types::String,
null: false,
description: 'External URL of the error.'
field :short_id, GraphQL::STRING_TYPE,
field :short_id, GraphQL::Types::String,
null: false,
description: 'Short ID (Sentry ID) of the error.'
field :status, Types::ErrorTracking::SentryErrorStatusEnum,
@ -52,15 +52,15 @@ module Types
field :frequency, [Types::ErrorTracking::SentryErrorFrequencyType],
null: false,
description: 'Last 24hr stats of the error.'
field :sentry_project_id, GraphQL::ID_TYPE,
field :sentry_project_id, GraphQL::Types::ID,
method: :project_id,
null: false,
description: 'ID of the project (Sentry project).'
field :sentry_project_name, GraphQL::STRING_TYPE,
field :sentry_project_name, GraphQL::Types::String,
method: :project_name,
null: false,
description: 'Name of the project affected by the error.'
field :sentry_project_slug, GraphQL::STRING_TYPE,
field :sentry_project_slug, GraphQL::Types::String,
method: :project_slug,
null: false,
description: 'Slug of the project affected by the error.'

View File

@ -9,7 +9,7 @@ module Types
authorize :read_event
field :id, GraphQL::ID_TYPE,
field :id, GraphQL::Types::ID,
description: 'ID of the event.',
null: false

View File

@ -9,11 +9,11 @@ module Types
present_using Releases::EvidencePresenter
field :id, GraphQL::ID_TYPE, null: false,
field :id, GraphQL::Types::ID, null: false,
description: 'ID of the evidence.'
field :sha, GraphQL::STRING_TYPE, null: true,
field :sha, GraphQL::Types::String, null: true,
description: 'SHA1 ID of the evidence hash.'
field :filepath, GraphQL::STRING_TYPE, null: true,
field :filepath, GraphQL::Types::String, null: true,
description: 'URL from where the evidence can be downloaded.'
field :collected_at, Types::TimeType, null: true,
description: 'Timestamp when the evidence was collected.'

View File

@ -6,11 +6,11 @@ module Types
authorize :admin_operations
field :id, GraphQL::ID_TYPE, null: false,
field :id, GraphQL::Types::ID, null: false,
description: 'Internal ID of the Grafana integration.'
field :grafana_url, GraphQL::STRING_TYPE, null: false,
field :grafana_url, GraphQL::Types::String, null: false,
description: 'URL for the Grafana host for the Grafana integration.'
field :enabled, GraphQL::BOOLEAN_TYPE, null: false,
field :enabled, GraphQL::Types::Boolean, null: false,
description: 'Indicates whether Grafana integration is enabled.'
field :created_at, Types::TimeType, null: false,
description: 'Timestamp of the issue\'s creation.'

View File

@ -9,12 +9,12 @@ module Types
expose_permissions Types::PermissionTypes::Group
field :web_url,
type: GraphQL::STRING_TYPE,
type: GraphQL::Types::String,
null: false,
description: 'Web URL of the group.'
field :avatar_url,
type: GraphQL::STRING_TYPE,
type: GraphQL::Types::String,
null: true,
description: 'Avatar URL of the group.'
@ -25,42 +25,42 @@ module Types
feature_flag: :custom_emoji
field :share_with_group_lock,
type: GraphQL::BOOLEAN_TYPE,
type: GraphQL::Types::Boolean,
null: true,
description: 'Indicates if sharing a project with another group within this group is prevented.'
field :project_creation_level,
type: GraphQL::STRING_TYPE,
type: GraphQL::Types::String,
null: true,
method: :project_creation_level_str,
description: 'The permission level required to create projects in the group.'
field :subgroup_creation_level,
type: GraphQL::STRING_TYPE,
type: GraphQL::Types::String,
null: true,
method: :subgroup_creation_level_str,
description: 'The permission level required to create subgroups within the group.'
field :require_two_factor_authentication,
type: GraphQL::BOOLEAN_TYPE,
type: GraphQL::Types::Boolean,
null: true,
description: 'Indicates if all users in this group are required to set up two-factor authentication.'
field :two_factor_grace_period,
type: GraphQL::INT_TYPE,
type: GraphQL::Types::Int,
null: true,
description: 'Time before two-factor authentication is enforced.'
field :auto_devops_enabled,
type: GraphQL::BOOLEAN_TYPE,
type: GraphQL::Types::Boolean,
null: true,
description: 'Indicates whether Auto DevOps is enabled for all projects within this group.'
field :emails_disabled,
type: GraphQL::BOOLEAN_TYPE,
type: GraphQL::Types::Boolean,
null: true,
description: 'Indicates if a group has email notifications disabled.'
field :mentions_disabled,
type: GraphQL::BOOLEAN_TYPE,
type: GraphQL::Types::Boolean,
null: true,
description: 'Indicates if a group is disabled from getting mentioned.'
@ -103,7 +103,7 @@ module Types
null: true,
description: 'A label available on this group.' do
argument :title,
type: GraphQL::STRING_TYPE,
type: GraphQL::Types::String,
required: true,
description: 'Title of the label.'
end
@ -120,7 +120,7 @@ module Types
authorize: :read_container_image
field :container_repositories_count,
type: GraphQL::INT_TYPE,
type: GraphQL::Types::Int,
null: false,
description: 'Number of container repositories in the group.'

View File

@ -4,7 +4,7 @@ module Types
module InvitationInterface
include BaseInterface
field :email, GraphQL::STRING_TYPE, null: false,
field :email, GraphQL::Types::String, null: false,
description: 'Email of the member to invite.'
field :access_level, Types::AccessLevelType, null: true,

View File

@ -15,7 +15,7 @@ module Types
next unless available_issue_states.include?(state.downcase)
field state,
GraphQL::INT_TYPE,
GraphQL::Types::Int,
null: true,
description: "Number of issues with status #{state.upcase} for the project"
end

View File

@ -15,23 +15,23 @@ module Types
present_using IssuePresenter
field :id, GraphQL::ID_TYPE, null: false,
field :id, GraphQL::Types::ID, null: false,
description: "ID of the issue."
field :iid, GraphQL::ID_TYPE, null: false,
field :iid, GraphQL::Types::ID, null: false,
description: "Internal ID of the issue."
field :title, GraphQL::STRING_TYPE, null: false,
field :title, GraphQL::Types::String, null: false,
description: 'Title of the issue.'
markdown_field :title_html, null: true
field :description, GraphQL::STRING_TYPE, null: true,
field :description, GraphQL::Types::String, null: true,
description: 'Description of the issue.'
markdown_field :description_html, null: true
field :state, IssueStateEnum, null: false,
description: 'State of the issue.'
field :reference, GraphQL::STRING_TYPE, null: false,
field :reference, GraphQL::Types::String, null: false,
description: 'Internal reference of the issue. Returned in shortened format by default.',
method: :to_reference do
argument :full, GraphQL::BOOLEAN_TYPE, required: false, default_value: false,
argument :full, GraphQL::Types::Boolean, required: false, default_value: false,
description: 'Boolean option specifying whether the reference should be returned in full.'
end
@ -51,42 +51,42 @@ module Types
field :due_date, Types::TimeType, null: true,
description: 'Due date of the issue.'
field :confidential, GraphQL::BOOLEAN_TYPE, null: false,
field :confidential, GraphQL::Types::Boolean, null: false,
description: 'Indicates the issue is confidential.'
field :discussion_locked, GraphQL::BOOLEAN_TYPE, null: false,
field :discussion_locked, GraphQL::Types::Boolean, null: false,
description: 'Indicates discussion is locked on the issue.'
field :upvotes, GraphQL::INT_TYPE, null: false,
field :upvotes, GraphQL::Types::Int, null: false,
description: 'Number of upvotes the issue has received.'
field :downvotes, GraphQL::INT_TYPE, null: false,
field :downvotes, GraphQL::Types::Int, null: false,
description: 'Number of downvotes the issue has received.'
field :user_notes_count, GraphQL::INT_TYPE, null: false,
field :user_notes_count, GraphQL::Types::Int, null: false,
description: 'Number of user notes of the issue.',
resolver: Resolvers::UserNotesCountResolver
field :user_discussions_count, GraphQL::INT_TYPE, null: false,
field :user_discussions_count, GraphQL::Types::Int, null: false,
description: 'Number of user discussions in the issue.',
resolver: Resolvers::UserDiscussionsCountResolver
field :web_path, GraphQL::STRING_TYPE, null: false, method: :issue_path,
field :web_path, GraphQL::Types::String, null: false, method: :issue_path,
description: 'Web path of the issue.'
field :web_url, GraphQL::STRING_TYPE, null: false,
field :web_url, GraphQL::Types::String, null: false,
description: 'Web URL of the issue.'
field :relative_position, GraphQL::INT_TYPE, null: true,
field :relative_position, GraphQL::Types::Int, null: true,
description: 'Relative position of the issue (used for positioning in epic tree and issue boards).'
field :participants, Types::UserType.connection_type, null: true, complexity: 5,
description: 'List of participants in the issue.'
field :emails_disabled, GraphQL::BOOLEAN_TYPE, null: false,
field :emails_disabled, GraphQL::Types::Boolean, null: false,
method: :project_emails_disabled?,
description: 'Indicates if a project has email notifications disabled: `true` if email notifications are disabled.'
field :subscribed, GraphQL::BOOLEAN_TYPE, method: :subscribed?, null: false, complexity: 5,
field :subscribed, GraphQL::Types::Boolean, method: :subscribed?, null: false, complexity: 5,
description: 'Indicates the currently logged in user is subscribed to the issue.'
field :time_estimate, GraphQL::INT_TYPE, null: false,
field :time_estimate, GraphQL::Types::Int, null: false,
description: 'Time estimate of the issue.'
field :total_time_spent, GraphQL::INT_TYPE, null: false,
field :total_time_spent, GraphQL::Types::Int, null: false,
description: 'Total time reported as spent on the issue.'
field :human_time_estimate, GraphQL::STRING_TYPE, null: true,
field :human_time_estimate, GraphQL::Types::String, null: true,
description: 'Human-readable time estimate of the issue.'
field :human_total_time_spent, GraphQL::STRING_TYPE, null: true,
field :human_total_time_spent, GraphQL::Types::String, null: true,
description: 'Human-readable total time reported as spent on the issue.'
field :closed_at, Types::TimeType, null: true,
@ -115,19 +115,19 @@ module Types
field :severity, Types::IssuableSeverityEnum, null: true,
description: 'Severity level of the incident.'
field :moved, GraphQL::BOOLEAN_TYPE, method: :moved?, null: true,
field :moved, GraphQL::Types::Boolean, method: :moved?, null: true,
description: 'Indicates if issue got moved from other project.'
field :moved_to, Types::IssueType, null: true,
description: 'Updated Issue after it got moved to another project.'
field :create_note_email, GraphQL::STRING_TYPE, null: true,
field :create_note_email, GraphQL::Types::String, null: true,
description: 'User specific email address for the issue.'
field :timelogs, Types::TimelogType.connection_type, null: false,
description: 'Timelogs on the issue.'
field :project_id, GraphQL::INT_TYPE, null: false, method: :project_id,
field :project_id, GraphQL::Types::Int, null: false, method: :project_id,
description: 'ID of the issue project.'
def author

View File

@ -5,19 +5,19 @@ module Types
class NegatedIssueFilterInputType < BaseInputObject
graphql_name 'NegatedIssueFilterInput'
argument :iids, [GraphQL::STRING_TYPE],
argument :iids, [GraphQL::Types::String],
required: false,
description: 'List of IIDs of issues to exclude. For example, `[1, 2]`.'
argument :label_name, [GraphQL::STRING_TYPE],
argument :label_name, [GraphQL::Types::String],
required: false,
description: 'Labels not applied to this issue.'
argument :milestone_title, [GraphQL::STRING_TYPE],
argument :milestone_title, [GraphQL::Types::String],
required: false,
description: 'Milestone not applied to this issue.'
argument :assignee_usernames, [GraphQL::STRING_TYPE],
argument :assignee_usernames, [GraphQL::Types::String],
required: false,
description: 'Usernames of users not assigned to the issue.'
argument :assignee_id, GraphQL::STRING_TYPE,
argument :assignee_id, GraphQL::Types::String,
required: false,
description: 'ID of a user not assigned to the issues.'
end

View File

@ -12,13 +12,13 @@ module Types
description: 'Timestamp of when the Jira import was scheduled.'
field :scheduled_by, Types::UserType, null: true,
description: 'User that started the Jira import.'
field :jira_project_key, GraphQL::STRING_TYPE, null: false,
field :jira_project_key, GraphQL::Types::String, null: false,
description: 'Project key for the imported Jira project.'
field :imported_issues_count, GraphQL::INT_TYPE, null: false,
field :imported_issues_count, GraphQL::Types::Int, null: false,
description: 'Count of issues that were successfully imported.'
field :failed_to_import_count, GraphQL::INT_TYPE, null: false,
field :failed_to_import_count, GraphQL::Types::Int, null: false,
description: 'Count of issues that failed to import.'
field :total_issue_count, GraphQL::INT_TYPE, null: false,
field :total_issue_count, GraphQL::Types::Int, null: false,
description: 'Total count of issues that were attempted to import.'
end
# rubocop: enable Graphql/AuthorizeTypes

View File

@ -6,17 +6,17 @@ module Types
class JiraUserType < BaseObject
graphql_name 'JiraUser'
field :jira_account_id, GraphQL::STRING_TYPE, null: false,
field :jira_account_id, GraphQL::Types::String, null: false,
description: 'Account ID of the Jira user.'
field :jira_display_name, GraphQL::STRING_TYPE, null: false,
field :jira_display_name, GraphQL::Types::String, null: false,
description: 'Display name of the Jira user.'
field :jira_email, GraphQL::STRING_TYPE, null: true,
field :jira_email, GraphQL::Types::String, null: true,
description: 'Email of the Jira user, returned only for users with public emails.'
field :gitlab_id, GraphQL::INT_TYPE, null: true,
field :gitlab_id, GraphQL::Types::Int, null: true,
description: 'ID of the matched GitLab user.'
field :gitlab_username, GraphQL::STRING_TYPE, null: true,
field :gitlab_username, GraphQL::Types::String, null: true,
description: 'Username of the matched GitLab user.'
field :gitlab_name, GraphQL::STRING_TYPE, null: true,
field :gitlab_name, GraphQL::Types::String, null: true,
description: 'Name of the matched GitLab user.'
end
# rubocop: enable Graphql/AuthorizeTypes

View File

@ -5,11 +5,11 @@ module Types
graphql_name 'JiraUsersMappingInputType'
argument :jira_account_id,
GraphQL::STRING_TYPE,
GraphQL::Types::String,
required: true,
description: 'Jira account ID of the user.'
argument :gitlab_id,
GraphQL::INT_TYPE,
GraphQL::Types::Int,
required: false,
description: 'ID of the GitLab user.'
end

View File

@ -8,16 +8,16 @@ module Types
authorize :read_label
field :id, GraphQL::ID_TYPE, null: false,
field :id, GraphQL::Types::ID, null: false,
description: 'Label ID.'
field :description, GraphQL::STRING_TYPE, null: true,
field :description, GraphQL::Types::String, null: true,
description: 'Description of the label (Markdown rendered as HTML for caching).'
markdown_field :description_html, null: true
field :title, GraphQL::STRING_TYPE, null: false,
field :title, GraphQL::Types::String, null: false,
description: 'Content of the label.'
field :color, GraphQL::STRING_TYPE, null: false,
field :color, GraphQL::Types::String, null: false,
description: 'Background color of the label.'
field :text_color, GraphQL::STRING_TYPE, null: false,
field :text_color, GraphQL::Types::String, null: false,
description: 'Text color of the label.'
field :created_at, Types::TimeType, null: false,
description: 'When this label was created.'

View File

@ -4,7 +4,7 @@ module Types
module MemberInterface
include BaseInterface
field :id, GraphQL::ID_TYPE, null: false,
field :id, GraphQL::Types::ID, null: false,
description: 'ID of the member.'
field :access_level, Types::AccessLevelType, null: true,

View File

@ -15,14 +15,14 @@ module Types
present_using MergeRequestPresenter
field :id, GraphQL::ID_TYPE, null: false,
field :id, GraphQL::Types::ID, null: false,
description: 'ID of the merge request.'
field :iid, GraphQL::STRING_TYPE, null: false,
field :iid, GraphQL::Types::String, null: false,
description: 'Internal ID of the merge request.'
field :title, GraphQL::STRING_TYPE, null: false,
field :title, GraphQL::Types::String, null: false,
description: 'Title of the merge request.'
markdown_field :title_html, null: true
field :description, GraphQL::STRING_TYPE, null: true,
field :description, GraphQL::Types::String, null: true,
description: 'Description of the merge request (Markdown rendered as HTML for caching).'
markdown_field :description_html, null: true
field :state, MergeRequestStateEnum, null: false,
@ -41,91 +41,91 @@ module Types
description: 'References of the base SHA, the head SHA, and the start SHA for this merge request.'
field :project, Types::ProjectType, null: false,
description: 'Alias for target_project.'
field :project_id, GraphQL::INT_TYPE, null: false, method: :target_project_id,
field :project_id, GraphQL::Types::Int, null: false, method: :target_project_id,
description: 'ID of the merge request project.'
field :source_project_id, GraphQL::INT_TYPE, null: true,
field :source_project_id, GraphQL::Types::Int, null: true,
description: 'ID of the merge request source project.'
field :target_project_id, GraphQL::INT_TYPE, null: false,
field :target_project_id, GraphQL::Types::Int, null: false,
description: 'ID of the merge request target project.'
field :source_branch, GraphQL::STRING_TYPE, null: false,
field :source_branch, GraphQL::Types::String, null: false,
description: 'Source branch of the merge request.'
field :source_branch_protected, GraphQL::BOOLEAN_TYPE, null: false, calls_gitaly: true,
field :source_branch_protected, GraphQL::Types::Boolean, null: false, calls_gitaly: true,
description: 'Indicates if the source branch is protected.'
field :target_branch, GraphQL::STRING_TYPE, null: false,
field :target_branch, GraphQL::Types::String, null: false,
description: 'Target branch of the merge request.'
field :work_in_progress, GraphQL::BOOLEAN_TYPE, method: :work_in_progress?, null: false,
field :work_in_progress, GraphQL::Types::Boolean, method: :work_in_progress?, null: false,
deprecated: { reason: 'Use `draft`', milestone: '13.12' },
description: 'Indicates if the merge request is a draft.'
field :draft, GraphQL::BOOLEAN_TYPE, method: :draft?, null: false,
field :draft, GraphQL::Types::Boolean, method: :draft?, null: false,
description: 'Indicates if the merge request is a draft.'
field :merge_when_pipeline_succeeds, GraphQL::BOOLEAN_TYPE, null: true,
field :merge_when_pipeline_succeeds, GraphQL::Types::Boolean, null: true,
description: 'Indicates if the merge has been set to be merged when its pipeline succeeds (MWPS).'
field :diff_head_sha, GraphQL::STRING_TYPE, null: true,
field :diff_head_sha, GraphQL::Types::String, null: true,
description: 'Diff head SHA of the merge request.'
field :diff_stats, [Types::DiffStatsType], null: true, calls_gitaly: true,
description: 'Details about which files were changed in this merge request.' do
argument :path, GraphQL::STRING_TYPE, required: false, description: 'A specific file-path.'
argument :path, GraphQL::Types::String, required: false, description: 'A specific file-path.'
end
field :diff_stats_summary, Types::DiffStatsSummaryType, null: true, calls_gitaly: true,
description: 'Summary of which files were changed in this merge request.'
field :merge_commit_sha, GraphQL::STRING_TYPE, null: true,
field :merge_commit_sha, GraphQL::Types::String, null: true,
description: 'SHA of the merge request commit (set once merged).'
field :user_notes_count, GraphQL::INT_TYPE, null: true,
field :user_notes_count, GraphQL::Types::Int, null: true,
description: 'User notes count of the merge request.',
resolver: Resolvers::UserNotesCountResolver
field :user_discussions_count, GraphQL::INT_TYPE, null: true,
field :user_discussions_count, GraphQL::Types::Int, null: true,
description: 'Number of user discussions in the merge request.',
resolver: Resolvers::UserDiscussionsCountResolver
field :should_remove_source_branch, GraphQL::BOOLEAN_TYPE, method: :should_remove_source_branch?, null: true,
field :should_remove_source_branch, GraphQL::Types::Boolean, method: :should_remove_source_branch?, null: true,
description: 'Indicates if the source branch of the merge request will be deleted after merge.'
field :force_remove_source_branch, GraphQL::BOOLEAN_TYPE, method: :force_remove_source_branch?, null: true,
field :force_remove_source_branch, GraphQL::Types::Boolean, method: :force_remove_source_branch?, null: true,
description: 'Indicates if the project settings will lead to source branch deletion after merge.'
field :merge_status, GraphQL::STRING_TYPE, method: :public_merge_status, null: true,
field :merge_status, GraphQL::Types::String, method: :public_merge_status, null: true,
description: 'Status of the merge request.',
deprecated: { reason: :renamed, replacement: 'MergeRequest.mergeStatusEnum', milestone: '14.0' }
field :merge_status_enum, ::Types::MergeRequests::MergeStatusEnum,
method: :public_merge_status, null: true,
description: 'Merge status of the merge request.'
field :in_progress_merge_commit_sha, GraphQL::STRING_TYPE, null: true,
field :in_progress_merge_commit_sha, GraphQL::Types::String, null: true,
description: 'Commit SHA of the merge request if merge is in progress.'
field :merge_error, GraphQL::STRING_TYPE, null: true,
field :merge_error, GraphQL::Types::String, null: true,
description: 'Error message due to a merge error.'
field :allow_collaboration, GraphQL::BOOLEAN_TYPE, null: true,
field :allow_collaboration, GraphQL::Types::Boolean, null: true,
description: 'Indicates if members of the target project can push to the fork.'
field :should_be_rebased, GraphQL::BOOLEAN_TYPE, method: :should_be_rebased?, null: false, calls_gitaly: true,
field :should_be_rebased, GraphQL::Types::Boolean, method: :should_be_rebased?, null: false, calls_gitaly: true,
description: 'Indicates if the merge request will be rebased.'
field :rebase_commit_sha, GraphQL::STRING_TYPE, null: true,
field :rebase_commit_sha, GraphQL::Types::String, null: true,
description: 'Rebase commit SHA of the merge request.'
field :rebase_in_progress, GraphQL::BOOLEAN_TYPE, method: :rebase_in_progress?, null: false, calls_gitaly: true,
field :rebase_in_progress, GraphQL::Types::Boolean, method: :rebase_in_progress?, null: false, calls_gitaly: true,
description: 'Indicates if there is a rebase currently in progress for the merge request.'
field :default_merge_commit_message, GraphQL::STRING_TYPE, null: true,
field :default_merge_commit_message, GraphQL::Types::String, null: true,
description: 'Default merge commit message of the merge request.'
field :default_merge_commit_message_with_description, GraphQL::STRING_TYPE, null: true,
field :default_merge_commit_message_with_description, GraphQL::Types::String, null: true,
description: 'Default merge commit message of the merge request with description.'
field :default_squash_commit_message, GraphQL::STRING_TYPE, null: true, calls_gitaly: true,
field :default_squash_commit_message, GraphQL::Types::String, null: true, calls_gitaly: true,
description: 'Default squash commit message of the merge request.'
field :merge_ongoing, GraphQL::BOOLEAN_TYPE, method: :merge_ongoing?, null: false,
field :merge_ongoing, GraphQL::Types::Boolean, method: :merge_ongoing?, null: false,
description: 'Indicates if a merge is currently occurring.'
field :source_branch_exists, GraphQL::BOOLEAN_TYPE,
field :source_branch_exists, GraphQL::Types::Boolean,
null: false, calls_gitaly: true,
method: :source_branch_exists?,
description: 'Indicates if the source branch of the merge request exists.'
field :target_branch_exists, GraphQL::BOOLEAN_TYPE,
field :target_branch_exists, GraphQL::Types::Boolean,
null: false, calls_gitaly: true,
method: :target_branch_exists?,
description: 'Indicates if the target branch of the merge request exists.'
field :diverged_from_target_branch, GraphQL::BOOLEAN_TYPE,
field :diverged_from_target_branch, GraphQL::Types::Boolean,
null: false, calls_gitaly: true,
method: :diverged_from_target_branch?,
description: 'Indicates if the source branch is behind the target branch.'
field :mergeable_discussions_state, GraphQL::BOOLEAN_TYPE, null: true,
field :mergeable_discussions_state, GraphQL::Types::Boolean, null: true,
description: 'Indicates if all discussions in the merge request have been resolved, allowing the merge request to be merged.'
field :web_url, GraphQL::STRING_TYPE, null: true,
field :web_url, GraphQL::Types::String, null: true,
description: 'Web URL of the merge request.'
field :upvotes, GraphQL::INT_TYPE, null: false,
field :upvotes, GraphQL::Types::Int, null: false,
description: 'Number of upvotes for the merge request.'
field :downvotes, GraphQL::INT_TYPE, null: false,
field :downvotes, GraphQL::Types::Int, null: false,
description: 'Number of downvotes for the merge request.'
field :head_pipeline, Types::Ci::PipelineType, null: true, method: :actual_head_pipeline,
@ -151,52 +151,52 @@ module Types
description: 'User who created this merge request.'
field :participants, Types::UserType.connection_type, null: true, complexity: 15,
description: 'Participants in the merge request. This includes the author, assignees, reviewers, and users mentioned in notes.'
field :subscribed, GraphQL::BOOLEAN_TYPE, method: :subscribed?, null: false, complexity: 5,
field :subscribed, GraphQL::Types::Boolean, method: :subscribed?, null: false, complexity: 5,
description: 'Indicates if the currently logged in user is subscribed to this merge request.'
field :labels, Types::LabelType.connection_type, null: true, complexity: 5,
description: 'Labels of the merge request.'
field :discussion_locked, GraphQL::BOOLEAN_TYPE,
field :discussion_locked, GraphQL::Types::Boolean,
description: 'Indicates if comments on the merge request are locked to members only.',
null: false
field :time_estimate, GraphQL::INT_TYPE, null: false,
field :time_estimate, GraphQL::Types::Int, null: false,
description: 'Time estimate of the merge request.'
field :total_time_spent, GraphQL::INT_TYPE, null: false,
field :total_time_spent, GraphQL::Types::Int, null: false,
description: 'Total time reported as spent on the merge request.'
field :human_time_estimate, GraphQL::STRING_TYPE, null: true,
field :human_time_estimate, GraphQL::Types::String, null: true,
description: 'Human-readable time estimate of the merge request.'
field :human_total_time_spent, GraphQL::STRING_TYPE, null: true,
field :human_total_time_spent, GraphQL::Types::String, null: true,
description: 'Human-readable total time reported as spent on the merge request.'
field :reference, GraphQL::STRING_TYPE, null: false, method: :to_reference,
field :reference, GraphQL::Types::String, null: false, method: :to_reference,
description: 'Internal reference of the merge request. Returned in shortened format by default.' do
argument :full, GraphQL::BOOLEAN_TYPE, required: false, default_value: false,
argument :full, GraphQL::Types::Boolean, required: false, default_value: false,
description: 'Boolean option specifying whether the reference should be returned in full.'
end
field :task_completion_status, Types::TaskCompletionStatus, null: false,
description: Types::TaskCompletionStatus.description
field :commit_count, GraphQL::INT_TYPE, null: true, method: :commits_count,
field :commit_count, GraphQL::Types::Int, null: true, method: :commits_count,
description: 'Number of commits in the merge request.'
field :conflicts, GraphQL::BOOLEAN_TYPE, null: false, method: :cannot_be_merged?,
field :conflicts, GraphQL::Types::Boolean, null: false, method: :cannot_be_merged?,
description: 'Indicates if the merge request has conflicts.'
field :auto_merge_enabled, GraphQL::BOOLEAN_TYPE, null: false,
field :auto_merge_enabled, GraphQL::Types::Boolean, null: false,
description: 'Indicates if auto merge is enabled for the merge request.'
field :approved_by, Types::UserType.connection_type, null: true,
description: 'Users who approved the merge request.'
field :squash_on_merge, GraphQL::BOOLEAN_TYPE, null: false, method: :squash_on_merge?,
field :squash_on_merge, GraphQL::Types::Boolean, null: false, method: :squash_on_merge?,
description: 'Indicates if squash on merge is enabled.'
field :squash, GraphQL::BOOLEAN_TYPE, null: false,
field :squash, GraphQL::Types::Boolean, null: false,
description: 'Indicates if squash on merge is enabled.'
field :available_auto_merge_strategies, [GraphQL::STRING_TYPE], null: true, calls_gitaly: true,
field :available_auto_merge_strategies, [GraphQL::Types::String], null: true, calls_gitaly: true,
description: 'Array of available auto merge strategies.'
field :has_ci, GraphQL::BOOLEAN_TYPE, null: false, method: :has_ci?,
field :has_ci, GraphQL::Types::Boolean, null: false, method: :has_ci?,
description: 'Indicates if the merge request has CI.'
field :mergeable, GraphQL::BOOLEAN_TYPE, null: false, method: :mergeable?, calls_gitaly: true,
field :mergeable, GraphQL::Types::Boolean, null: false, method: :mergeable?, calls_gitaly: true,
description: 'Indicates if the merge request is mergeable.'
field :commits_without_merge_commits, Types::CommitType.connection_type, null: true,
calls_gitaly: true, description: 'Merge request commits excluding merge commits.'
field :security_auto_fix, GraphQL::BOOLEAN_TYPE, null: true,
field :security_auto_fix, GraphQL::Types::Boolean, null: true,
description: 'Indicates if the merge request is created by @GitLab-Security-Bot.'
field :auto_merge_strategy, GraphQL::STRING_TYPE, null: true,
field :auto_merge_strategy, GraphQL::Types::String, null: true,
description: 'Selected auto merge strategy.'
field :merge_user, Types::UserType, null: true,
description: 'User who merged this merge request.'

View File

@ -7,11 +7,11 @@ module Types
authorize :read_instance_metadata
field :enabled, GraphQL::BOOLEAN_TYPE, null: false,
field :enabled, GraphQL::Types::Boolean, null: false,
description: 'Indicates whether the Kubernetes Agent Server is enabled.'
field :version, GraphQL::STRING_TYPE, null: true,
field :version, GraphQL::Types::String, null: true,
description: 'KAS version.'
field :external_url, GraphQL::STRING_TYPE, null: true,
field :external_url, GraphQL::Types::String, null: true,
description: 'The URL used by the Agents to communicate with KAS.'
end
end

View File

@ -6,9 +6,9 @@ module Types
authorize :read_instance_metadata
field :version, GraphQL::STRING_TYPE, null: false,
field :version, GraphQL::Types::String, null: false,
description: 'Version.'
field :revision, GraphQL::STRING_TYPE, null: false,
field :revision, GraphQL::Types::String, null: false,
description: 'Revision.'
field :kas, ::Types::Metadata::KasType, null: false,
description: 'Metadata about KAS.'

View File

@ -7,10 +7,10 @@ module Types
class DashboardType < ::Types::BaseObject
graphql_name 'MetricsDashboard'
field :path, GraphQL::STRING_TYPE, null: true,
field :path, GraphQL::Types::String, null: true,
description: 'Path to a file with the dashboard definition.'
field :schema_validation_warnings, [GraphQL::STRING_TYPE], null: true,
field :schema_validation_warnings, [GraphQL::Types::String], null: true,
description: 'Dashboard schema validation warnings.'
field :annotations, Types::Metrics::Dashboards::AnnotationType.connection_type, null: true,

View File

@ -7,13 +7,13 @@ module Types
authorize :read_metrics_dashboard_annotation
graphql_name 'MetricsDashboardAnnotation'
field :description, GraphQL::STRING_TYPE, null: true,
field :description, GraphQL::Types::String, null: true,
description: 'Description of the annotation.'
field :id, GraphQL::ID_TYPE, null: false,
field :id, GraphQL::Types::ID, null: false,
description: 'ID of the annotation.'
field :panel_id, GraphQL::STRING_TYPE, null: true,
field :panel_id, GraphQL::Types::String, null: true,
description: 'ID of a dashboard panel to which the annotation should be scoped.'
field :starting_at, Types::TimeType, null: true,

View File

@ -7,10 +7,10 @@ module Types
authorize :read_milestone
field :total_issues_count, GraphQL::INT_TYPE, null: true,
field :total_issues_count, GraphQL::Types::Int, null: true,
description: 'Total number of issues associated with the milestone.'
field :closed_issues_count, GraphQL::INT_TYPE, null: true,
field :closed_issues_count, GraphQL::Types::Int, null: true,
description: 'Number of closed issues associated with the milestone.'
end
end

View File

@ -11,25 +11,25 @@ module Types
alias_method :milestone, :object
field :id, GraphQL::ID_TYPE, null: false,
field :id, GraphQL::Types::ID, null: false,
description: 'ID of the milestone.'
field :iid, GraphQL::ID_TYPE, null: false,
field :iid, GraphQL::Types::ID, null: false,
description: "Internal ID of the milestone."
field :title, GraphQL::STRING_TYPE, null: false,
field :title, GraphQL::Types::String, null: false,
description: 'Title of the milestone.'
field :description, GraphQL::STRING_TYPE, null: true,
field :description, GraphQL::Types::String, null: true,
description: 'Description of the milestone.'
field :state, Types::MilestoneStateEnum, null: false,
description: 'State of the milestone.'
field :expired, GraphQL::BOOLEAN_TYPE, null: false,
field :expired, GraphQL::Types::Boolean, null: false,
description: 'Expired state of the milestone (a milestone is expired when the due date is past the current date). Defaults to `false` when due date has not been set.'
field :web_path, GraphQL::STRING_TYPE, null: false, method: :milestone_path,
field :web_path, GraphQL::Types::String, null: false, method: :milestone_path,
description: 'Web path of the milestone.'
field :due_date, Types::TimeType, null: true,
@ -44,15 +44,15 @@ module Types
field :updated_at, Types::TimeType, null: false,
description: 'Timestamp of last milestone update.'
field :project_milestone, GraphQL::BOOLEAN_TYPE, null: false,
field :project_milestone, GraphQL::Types::Boolean, null: false,
description: 'Indicates if milestone is at project level.',
method: :project_milestone?
field :group_milestone, GraphQL::BOOLEAN_TYPE, null: false,
field :group_milestone, GraphQL::Types::Boolean, null: false,
description: 'Indicates if milestone is at group level.',
method: :group_milestone?
field :subgroup_milestone, GraphQL::BOOLEAN_TYPE, null: false,
field :subgroup_milestone, GraphQL::Types::Boolean, null: false,
description: 'Indicates if milestone is at subgroup level.',
method: :subgroup_milestone?

View File

@ -8,9 +8,9 @@ module Types
authorize :read_package_settings
field :maven_duplicates_allowed, GraphQL::BOOLEAN_TYPE, null: false, description: 'Indicates whether duplicate Maven packages are allowed for this namespace.'
field :maven_duplicates_allowed, GraphQL::Types::Boolean, null: false, description: 'Indicates whether duplicate Maven packages are allowed for this namespace.'
field :maven_duplicate_exception_regex, Types::UntrustedRegexp, null: true, description: 'When maven_duplicates_allowed is false, you can publish duplicate packages with names that match this regex. Otherwise, this setting has no effect.'
field :generic_duplicates_allowed, GraphQL::BOOLEAN_TYPE, null: false, description: 'Indicates whether duplicate generic packages are allowed for this namespace.'
field :generic_duplicates_allowed, GraphQL::Types::Boolean, null: false, description: 'Indicates whether duplicate generic packages are allowed for this namespace.'
field :generic_duplicate_exception_regex, Types::UntrustedRegexp, null: true, description: 'When generic_duplicates_allowed is false, you can publish duplicate packages with names that match this regex. Otherwise, this setting has no effect.'
end
end

View File

@ -6,27 +6,27 @@ module Types
authorize :read_namespace
field :id, GraphQL::ID_TYPE, null: false,
field :id, GraphQL::Types::ID, null: false,
description: 'ID of the namespace.'
field :name, GraphQL::STRING_TYPE, null: false,
field :name, GraphQL::Types::String, null: false,
description: 'Name of the namespace.'
field :path, GraphQL::STRING_TYPE, null: false,
field :path, GraphQL::Types::String, null: false,
description: 'Path of the namespace.'
field :full_name, GraphQL::STRING_TYPE, null: false,
field :full_name, GraphQL::Types::String, null: false,
description: 'Full name of the namespace.'
field :full_path, GraphQL::ID_TYPE, null: false,
field :full_path, GraphQL::Types::ID, null: false,
description: 'Full path of the namespace.'
field :description, GraphQL::STRING_TYPE, null: true,
field :description, GraphQL::Types::String, null: true,
description: 'Description of the namespace.'
markdown_field :description_html, null: true
field :visibility, GraphQL::STRING_TYPE, null: true,
field :visibility, GraphQL::Types::String, null: true,
description: 'Visibility of the namespace.'
field :lfs_enabled, GraphQL::BOOLEAN_TYPE, null: true, method: :lfs_enabled?,
field :lfs_enabled, GraphQL::Types::Boolean, null: true, method: :lfs_enabled?,
description: 'Indicates if Large File Storage (LFS) is enabled for namespace.'
field :request_access_enabled, GraphQL::BOOLEAN_TYPE, null: true,
field :request_access_enabled, GraphQL::Types::Boolean, null: true,
description: 'Indicates if users can request access to namespace.'
field :root_storage_statistics, Types::RootStorageStatisticsType,

View File

@ -5,13 +5,13 @@ module Types
class DiffImagePositionInputType < DiffPositionBaseInputType
graphql_name 'DiffImagePositionInput'
argument :x, GraphQL::INT_TYPE, required: true,
argument :x, GraphQL::Types::Int, required: true,
description: copy_field_description(Types::Notes::DiffPositionType, :x)
argument :y, GraphQL::INT_TYPE, required: true,
argument :y, GraphQL::Types::Int, required: true,
description: copy_field_description(Types::Notes::DiffPositionType, :y)
argument :width, GraphQL::INT_TYPE, required: true,
argument :width, GraphQL::Types::Int, required: true,
description: copy_field_description(Types::Notes::DiffPositionType, :width)
argument :height, GraphQL::INT_TYPE, required: true,
argument :height, GraphQL::Types::Int, required: true,
description: copy_field_description(Types::Notes::DiffPositionType, :height)
end
end

View File

@ -3,11 +3,11 @@
module Types
module Notes
class DiffPositionBaseInputType < BaseInputObject
argument :head_sha, GraphQL::STRING_TYPE, required: true,
argument :head_sha, GraphQL::Types::String, required: true,
description: copy_field_description(Types::DiffRefsType, :head_sha)
argument :base_sha, GraphQL::STRING_TYPE, required: false,
argument :base_sha, GraphQL::Types::String, required: false,
description: copy_field_description(Types::DiffRefsType, :base_sha)
argument :start_sha, GraphQL::STRING_TYPE, required: true,
argument :start_sha, GraphQL::Types::String, required: true,
description: copy_field_description(Types::DiffRefsType, :start_sha)
argument :paths,

View File

@ -5,9 +5,9 @@ module Types
class DiffPositionInputType < DiffPositionBaseInputType
graphql_name 'DiffPositionInput'
argument :old_line, GraphQL::INT_TYPE, required: false,
argument :old_line, GraphQL::Types::Int, required: false,
description: copy_field_description(Types::Notes::DiffPositionType, :old_line)
argument :new_line, GraphQL::INT_TYPE, required: false,
argument :new_line, GraphQL::Types::Int, required: false,
description: copy_field_description(Types::Notes::DiffPositionType, :new_line)
end
end

View File

@ -10,29 +10,29 @@ module Types
field :diff_refs, Types::DiffRefsType, null: false,
description: 'Information about the branch, HEAD, and base at the time of commenting.'
field :file_path, GraphQL::STRING_TYPE, null: false,
field :file_path, GraphQL::Types::String, null: false,
description: 'Path of the file that was changed.'
field :old_path, GraphQL::STRING_TYPE, null: true,
field :old_path, GraphQL::Types::String, null: true,
description: 'Path of the file on the start SHA.'
field :new_path, GraphQL::STRING_TYPE, null: true,
field :new_path, GraphQL::Types::String, null: true,
description: 'Path of the file on the HEAD SHA.'
field :position_type, Types::Notes::PositionTypeEnum, null: false,
description: 'Type of file the position refers to.'
# Fields for text positions
field :old_line, GraphQL::INT_TYPE, null: true,
field :old_line, GraphQL::Types::Int, null: true,
description: 'Line on start SHA that was changed.'
field :new_line, GraphQL::INT_TYPE, null: true,
field :new_line, GraphQL::Types::Int, null: true,
description: 'Line on HEAD SHA that was changed.'
# Fields for image positions
field :x, GraphQL::INT_TYPE, null: true,
field :x, GraphQL::Types::Int, null: true,
description: 'X position of the note.'
field :y, GraphQL::INT_TYPE, null: true,
field :y, GraphQL::Types::Int, null: true,
description: 'Y position of the note.'
field :width, GraphQL::INT_TYPE, null: true,
field :width, GraphQL::Types::Int, null: true,
description: 'Total width of the image.'
field :height, GraphQL::INT_TYPE, null: true,
field :height, GraphQL::Types::Int, null: true,
description: 'Total height of the image.'
def old_line

View File

@ -22,13 +22,13 @@ module Types
null: false,
description: 'User who wrote this note.'
field :system, GraphQL::BOOLEAN_TYPE,
field :system, GraphQL::Types::Boolean,
null: false,
description: 'Indicates whether this note was created by the system or by a user.'
field :system_note_icon_name, GraphQL::STRING_TYPE, null: true,
field :system_note_icon_name, GraphQL::Types::String, null: true,
description: 'Name of the icon corresponding to a system note.'
field :body, GraphQL::STRING_TYPE,
field :body, GraphQL::Types::String,
null: false,
method: :note,
description: 'Content of the note.'
@ -43,10 +43,10 @@ module Types
description: 'The discussion this note is a part of.'
field :position, Types::Notes::DiffPositionType, null: true,
description: 'The position of this note on a diff.'
field :confidential, GraphQL::BOOLEAN_TYPE, null: true,
field :confidential, GraphQL::Types::Boolean, null: true,
description: 'Indicates if this note is confidential.',
method: :confidential?
field :url, GraphQL::STRING_TYPE,
field :url, GraphQL::Types::String,
null: true,
description: 'URL to view this Note in the Web UI.'

View File

@ -6,19 +6,19 @@ module Types
class UpdateDiffImagePositionInputType < BaseInputObject
graphql_name 'UpdateDiffImagePositionInput'
argument :x, GraphQL::INT_TYPE,
argument :x, GraphQL::Types::Int,
required: false,
description: copy_field_description(Types::Notes::DiffPositionType, :x)
argument :y, GraphQL::INT_TYPE,
argument :y, GraphQL::Types::Int,
required: false,
description: copy_field_description(Types::Notes::DiffPositionType, :y)
argument :width, GraphQL::INT_TYPE,
argument :width, GraphQL::Types::Int,
required: false,
description: copy_field_description(Types::Notes::DiffPositionType, :width)
argument :height, GraphQL::INT_TYPE,
argument :height, GraphQL::Types::Int,
required: false,
description: copy_field_description(Types::Notes::DiffPositionType, :height)

View File

@ -8,10 +8,10 @@ module Types
graphql_name 'PackageComposerJsonType'
description 'Represents a composer JSON file'
field :name, GraphQL::STRING_TYPE, null: true, description: 'The name set in the Composer JSON file.'
field :type, GraphQL::STRING_TYPE, null: true, description: 'The type set in the Composer JSON file.'
field :license, GraphQL::STRING_TYPE, null: true, description: 'The license set in the Composer JSON file.'
field :version, GraphQL::STRING_TYPE, null: true, description: 'The version set in the Composer JSON file.'
field :name, GraphQL::Types::String, null: true, description: 'The name set in the Composer JSON file.'
field :type, GraphQL::Types::String, null: true, description: 'The type set in the Composer JSON file.'
field :license, GraphQL::Types::String, null: true, description: 'The license set in the Composer JSON file.'
field :version, GraphQL::Types::String, null: true, description: 'The version set in the Composer JSON file.'
end
end
end

View File

@ -9,7 +9,7 @@ module Types
authorize :read_package
field :target_sha, GraphQL::STRING_TYPE, null: false, description: 'Target SHA of the package.'
field :target_sha, GraphQL::Types::String, null: false, description: 'Target SHA of the package.'
field :composer_json, Types::Packages::Composer::JsonType, null: false, description: 'Data of the Composer JSON file.'
end
end

View File

@ -12,9 +12,9 @@ module Types
authorize :read_package
field :id, ::Types::GlobalIDType[::Packages::Conan::FileMetadatum], null: false, description: 'ID of the metadatum.'
field :recipe_revision, GraphQL::STRING_TYPE, null: false, description: 'Revision of the Conan recipe.'
field :package_revision, GraphQL::STRING_TYPE, null: true, description: 'Revision of the package.'
field :conan_package_reference, GraphQL::STRING_TYPE, null: true, description: 'Reference of the Conan package.'
field :recipe_revision, GraphQL::Types::String, null: false, description: 'Revision of the Conan recipe.'
field :package_revision, GraphQL::Types::String, null: true, description: 'Revision of the package.'
field :conan_package_reference, GraphQL::Types::String, null: true, description: 'Reference of the Conan package.'
field :conan_file_type, ::Types::Packages::Conan::MetadatumFileTypeEnum, null: false, description: 'Type of the Conan file.'
end
end

View File

@ -12,10 +12,10 @@ module Types
field :id, ::Types::GlobalIDType[::Packages::Conan::Metadatum], null: false, description: 'ID of the metadatum.'
field :created_at, Types::TimeType, null: false, description: 'Date of creation.'
field :updated_at, Types::TimeType, null: false, description: 'Date of most recent update.'
field :package_username, GraphQL::STRING_TYPE, null: false, description: 'Username of the Conan package.'
field :package_channel, GraphQL::STRING_TYPE, null: false, description: 'Channel of the Conan package.'
field :recipe, GraphQL::STRING_TYPE, null: false, description: 'Recipe of the Conan package.'
field :recipe_path, GraphQL::STRING_TYPE, null: false, description: 'Recipe path of the Conan package.'
field :package_username, GraphQL::Types::String, null: false, description: 'Username of the Conan package.'
field :package_channel, GraphQL::Types::String, null: false, description: 'Channel of the Conan package.'
field :recipe, GraphQL::Types::String, null: false, description: 'Recipe of the Conan package.'
field :recipe_path, GraphQL::Types::String, null: false, description: 'Recipe path of the Conan package.'
end
end
end

View File

@ -12,10 +12,10 @@ module Types
field :id, ::Types::GlobalIDType[::Packages::Maven::Metadatum], null: false, description: 'ID of the metadatum.'
field :created_at, Types::TimeType, null: false, description: 'Date of creation.'
field :updated_at, Types::TimeType, null: false, description: 'Date of most recent update.'
field :path, GraphQL::STRING_TYPE, null: false, description: 'Path of the Maven package.'
field :app_group, GraphQL::STRING_TYPE, null: false, description: 'App group of the Maven package.'
field :app_version, GraphQL::STRING_TYPE, null: true, description: 'App version of the Maven package.'
field :app_name, GraphQL::STRING_TYPE, null: false, description: 'App name of the Maven package.'
field :path, GraphQL::Types::String, null: false, description: 'Path of the Maven package.'
field :app_group, GraphQL::Types::String, null: false, description: 'App group of the Maven package.'
field :app_version, GraphQL::Types::String, null: true, description: 'App version of the Maven package.'
field :app_name, GraphQL::Types::String, null: false, description: 'App name of the Maven package.'
end
end
end

View File

@ -10,9 +10,9 @@ module Types
authorize :read_package
field :id, ::Types::GlobalIDType[::Packages::Nuget::Metadatum], null: false, description: 'ID of the metadatum.'
field :license_url, GraphQL::STRING_TYPE, null: false, description: 'License URL of the Nuget package.'
field :project_url, GraphQL::STRING_TYPE, null: false, description: 'Project URL of the Nuget package.'
field :icon_url, GraphQL::STRING_TYPE, null: false, description: 'Icon URL of the Nuget package.'
field :license_url, GraphQL::Types::String, null: false, description: 'License URL of the Nuget package.'
field :project_url, GraphQL::Types::String, null: false, description: 'Project URL of the Nuget package.'
field :icon_url, GraphQL::Types::String, null: false, description: 'Icon URL of the Nuget package.'
end
end
end

View File

@ -10,12 +10,12 @@ module Types
field :id, ::Types::GlobalIDType[::Packages::PackageFile], null: false, description: 'ID of the file.'
field :created_at, Types::TimeType, null: false, description: 'The created date.'
field :updated_at, Types::TimeType, null: false, description: 'The updated date.'
field :size, GraphQL::STRING_TYPE, null: false, description: 'Size of the package file.'
field :file_name, GraphQL::STRING_TYPE, null: false, description: 'Name of the package file.'
field :download_path, GraphQL::STRING_TYPE, null: false, description: 'Download path of the package file.'
field :file_md5, GraphQL::STRING_TYPE, null: true, description: 'Md5 of the package file.'
field :file_sha1, GraphQL::STRING_TYPE, null: true, description: 'Sha1 of the package file.'
field :file_sha256, GraphQL::STRING_TYPE, null: true, description: 'Sha256 of the package file.'
field :size, GraphQL::Types::String, null: false, description: 'Size of the package file.'
field :file_name, GraphQL::Types::String, null: false, description: 'Name of the package file.'
field :download_path, GraphQL::Types::String, null: false, description: 'Download path of the package file.'
field :file_md5, GraphQL::Types::String, null: true, description: 'Md5 of the package file.'
field :file_sha1, GraphQL::Types::String, null: true, description: 'Sha1 of the package file.'
field :file_sha256, GraphQL::Types::String, null: true, description: 'Sha256 of the package file.'
field :file_metadata, Types::Packages::FileMetadataType, null: true,
description: 'File metadata.'

View File

@ -7,8 +7,8 @@ module Types
description 'Represents a package tag'
authorize :read_package
field :id, GraphQL::ID_TYPE, null: false, description: 'The ID of the tag.'
field :name, GraphQL::STRING_TYPE, null: false, description: 'The name of the tag.'
field :id, GraphQL::Types::ID, null: false, description: 'The ID of the tag.'
field :name, GraphQL::Types::String, null: false, description: 'The name of the tag.'
field :created_at, Types::TimeType, null: false, description: 'The created date.'
field :updated_at, Types::TimeType, null: false, description: 'The updated date.'
end

View File

@ -11,10 +11,10 @@ module Types
field :id, ::Types::GlobalIDType[::Packages::Package], null: false,
description: 'ID of the package.'
field :name, GraphQL::STRING_TYPE, null: false, description: 'Name of the package.'
field :name, GraphQL::Types::String, null: false, description: 'Name of the package.'
field :created_at, Types::TimeType, null: false, description: 'Date of creation.'
field :updated_at, Types::TimeType, null: false, description: 'Date of most recent update.'
field :version, GraphQL::STRING_TYPE, null: true, description: 'Version string.'
field :version, GraphQL::Types::String, null: true, description: 'Version string.'
field :package_type, Types::Packages::PackageTypeEnum, null: false, description: 'Package type.'
field :tags, Types::Packages::PackageTagType.connection_type, null: true, description: 'Package tags.'
field :project, Types::ProjectType, null: false, description: 'Project where the package is stored.'

View File

@ -10,7 +10,7 @@ module Types
authorize :read_package
field :id, ::Types::GlobalIDType[::Packages::Pypi::Metadatum], null: false, description: 'ID of the metadatum.'
field :required_python, GraphQL::STRING_TYPE, null: true, description: 'Required Python version of the Pypi package.'
field :required_python, GraphQL::Types::String, null: true, description: 'Required Python version of the Pypi package.'
end
end
end

View File

@ -24,7 +24,7 @@ module Types
def self.permission_field(name, **kword_args)
kword_args = kword_args.reverse_merge(
name: name,
type: GraphQL::BOOLEAN_TYPE,
type: GraphQL::Types::Boolean,
description: "Indicates the user can perform `#{name}` on this resource",
null: false)

View File

@ -8,44 +8,44 @@ module Types
expose_permissions Types::PermissionTypes::Project
field :id, GraphQL::ID_TYPE, null: false,
field :id, GraphQL::Types::ID, null: false,
description: 'ID of the project.'
field :full_path, GraphQL::ID_TYPE, null: false,
field :full_path, GraphQL::Types::ID, null: false,
description: 'Full path of the project.'
field :path, GraphQL::STRING_TYPE, null: false,
field :path, GraphQL::Types::String, null: false,
description: 'Path of the project.'
field :sast_ci_configuration, Types::CiConfiguration::Sast::Type, null: true,
calls_gitaly: true,
description: 'SAST CI configuration for the project.'
field :name_with_namespace, GraphQL::STRING_TYPE, null: false,
field :name_with_namespace, GraphQL::Types::String, null: false,
description: 'Full name of the project with its namespace.'
field :name, GraphQL::STRING_TYPE, null: false,
field :name, GraphQL::Types::String, null: false,
description: 'Name of the project (without namespace).'
field :description, GraphQL::STRING_TYPE, null: true,
field :description, GraphQL::Types::String, null: true,
description: 'Short description of the project.'
markdown_field :description_html, null: true
field :tag_list, GraphQL::STRING_TYPE, null: true,
field :tag_list, GraphQL::Types::String, null: true,
deprecated: { reason: 'Use `topics`', milestone: '13.12' },
description: 'List of project topics (not Git tags).'
field :topics, [GraphQL::STRING_TYPE], null: true,
field :topics, [GraphQL::Types::String], null: true,
description: 'List of project topics.'
field :ssh_url_to_repo, GraphQL::STRING_TYPE, null: true,
field :ssh_url_to_repo, GraphQL::Types::String, null: true,
description: 'URL to connect to the project via SSH.'
field :http_url_to_repo, GraphQL::STRING_TYPE, null: true,
field :http_url_to_repo, GraphQL::Types::String, null: true,
description: 'URL to connect to the project via HTTPS.'
field :web_url, GraphQL::STRING_TYPE, null: true,
field :web_url, GraphQL::Types::String, null: true,
description: 'Web URL of the project.'
field :star_count, GraphQL::INT_TYPE, null: false,
field :star_count, GraphQL::Types::Int, null: false,
description: 'Number of times the project has been starred.'
field :forks_count, GraphQL::INT_TYPE, null: false, calls_gitaly: true, # 4 times
field :forks_count, GraphQL::Types::Int, null: false, calls_gitaly: true, # 4 times
description: 'Number of times the project has been forked.'
field :created_at, Types::TimeType, null: true,
@ -53,26 +53,26 @@ module Types
field :last_activity_at, Types::TimeType, null: true,
description: 'Timestamp of the project last activity.'
field :archived, GraphQL::BOOLEAN_TYPE, null: true,
field :archived, GraphQL::Types::Boolean, null: true,
description: 'Indicates the archived status of the project.'
field :visibility, GraphQL::STRING_TYPE, null: true,
field :visibility, GraphQL::Types::String, null: true,
description: 'Visibility of the project.'
field :shared_runners_enabled, GraphQL::BOOLEAN_TYPE, null: true,
field :shared_runners_enabled, GraphQL::Types::Boolean, null: true,
description: 'Indicates if shared runners are enabled for the project.'
field :lfs_enabled, GraphQL::BOOLEAN_TYPE, null: true,
field :lfs_enabled, GraphQL::Types::Boolean, null: true,
description: 'Indicates if the project has Large File Storage (LFS) enabled.'
field :merge_requests_ff_only_enabled, GraphQL::BOOLEAN_TYPE, null: true,
field :merge_requests_ff_only_enabled, GraphQL::Types::Boolean, null: true,
description: 'Indicates if no merge commits should be created and all merges should instead be fast-forwarded, which means that merging is only allowed if the branch could be fast-forwarded.'
field :service_desk_enabled, GraphQL::BOOLEAN_TYPE, null: true,
field :service_desk_enabled, GraphQL::Types::Boolean, null: true,
description: 'Indicates if the project has service desk enabled.'
field :service_desk_address, GraphQL::STRING_TYPE, null: true,
field :service_desk_address, GraphQL::Types::String, null: true,
description: 'E-mail address of the service desk.'
field :avatar_url, GraphQL::STRING_TYPE, null: true, calls_gitaly: true,
field :avatar_url, GraphQL::Types::String, null: true, calls_gitaly: true,
description: 'URL to avatar image file of the project.'
{
@ -90,36 +90,36 @@ module Types
end
end
field :jobs_enabled, GraphQL::BOOLEAN_TYPE, null: true,
field :jobs_enabled, GraphQL::Types::Boolean, null: true,
description: 'Indicates if CI/CD pipeline jobs are enabled for the current user.'
field :public_jobs, GraphQL::BOOLEAN_TYPE, method: :public_builds, null: true,
field :public_jobs, GraphQL::Types::Boolean, method: :public_builds, null: true,
description: 'Indicates if there is public access to pipelines and job details of the project, including output logs and artifacts.'
field :open_issues_count, GraphQL::INT_TYPE, null: true,
field :open_issues_count, GraphQL::Types::Int, null: true,
description: 'Number of open issues for the project.'
field :import_status, GraphQL::STRING_TYPE, null: true,
field :import_status, GraphQL::Types::String, null: true,
description: 'Status of import background job of the project.'
field :jira_import_status, GraphQL::STRING_TYPE, null: true,
field :jira_import_status, GraphQL::Types::String, null: true,
description: 'Status of Jira import background job of the project.'
field :only_allow_merge_if_pipeline_succeeds, GraphQL::BOOLEAN_TYPE, null: true,
field :only_allow_merge_if_pipeline_succeeds, GraphQL::Types::Boolean, null: true,
description: 'Indicates if merge requests of the project can only be merged with successful jobs.'
field :allow_merge_on_skipped_pipeline, GraphQL::BOOLEAN_TYPE, null: true,
field :allow_merge_on_skipped_pipeline, GraphQL::Types::Boolean, null: true,
description: 'If `only_allow_merge_if_pipeline_succeeds` is true, indicates if merge requests of the project can also be merged with skipped jobs.'
field :request_access_enabled, GraphQL::BOOLEAN_TYPE, null: true,
field :request_access_enabled, GraphQL::Types::Boolean, null: true,
description: 'Indicates if users can request member access to the project.'
field :only_allow_merge_if_all_discussions_are_resolved, GraphQL::BOOLEAN_TYPE, null: true,
field :only_allow_merge_if_all_discussions_are_resolved, GraphQL::Types::Boolean, null: true,
description: 'Indicates if merge requests of the project can only be merged when all the discussions are resolved.'
field :printing_merge_request_link_enabled, GraphQL::BOOLEAN_TYPE, null: true,
field :printing_merge_request_link_enabled, GraphQL::Types::Boolean, null: true,
description: 'Indicates if a link to create or view a merge request should display after a push to Git repositories of the project from the command line.'
field :remove_source_branch_after_merge, GraphQL::BOOLEAN_TYPE, null: true,
field :remove_source_branch_after_merge, GraphQL::Types::Boolean, null: true,
description: 'Indicates if `Delete source branch` option should be enabled by default for all new merge requests of the project.'
field :autoclose_referenced_issues, GraphQL::BOOLEAN_TYPE, null: true,
field :autoclose_referenced_issues, GraphQL::Types::Boolean, null: true,
description: 'Indicates if issues referenced by merge requests and commits within the default branch are closed automatically.'
field :suggestion_commit_message, GraphQL::STRING_TYPE, null: true,
field :suggestion_commit_message, GraphQL::Types::String, null: true,
description: 'The commit message used to apply merge request suggestions.'
field :squash_read_only, GraphQL::BOOLEAN_TYPE, null: false, method: :squash_readonly?,
field :squash_read_only, GraphQL::Types::Boolean, null: false, method: :squash_readonly?,
description: 'Indicates if `squashReadOnly` is enabled.'
field :namespace, Types::NamespaceType, null: true,
@ -318,14 +318,14 @@ module Types
description: 'Container repositories of the project.',
resolver: Resolvers::ContainerRepositoriesResolver
field :container_repositories_count, GraphQL::INT_TYPE, null: false,
field :container_repositories_count, GraphQL::Types::Int, null: false,
description: 'Number of container repositories in the project.'
field :label,
Types::LabelType,
null: true,
description: 'A label available on this project.' do
argument :title, GraphQL::STRING_TYPE,
argument :title, GraphQL::Types::String,
required: true,
description: 'Title of the label.'
end

View File

@ -8,9 +8,9 @@ module Types
# TODO: Add all the fields that we want to expose for the project services integrations
# https://gitlab.com/gitlab-org/gitlab/-/issues/213088
field :type, GraphQL::STRING_TYPE, null: true,
field :type, GraphQL::Types::String, null: true,
description: 'Class name of the service.'
field :active, GraphQL::BOOLEAN_TYPE, null: true,
field :active, GraphQL::Types::Boolean, null: true,
description: 'Indicates if the service is active.'
definition_methods do

View File

@ -7,12 +7,12 @@ module Types
class JiraProjectType < BaseObject
graphql_name 'JiraProject'
field :key, GraphQL::STRING_TYPE, null: false,
field :key, GraphQL::Types::String, null: false,
description: 'Key of the Jira project.'
field :project_id, GraphQL::INT_TYPE, null: false,
field :project_id, GraphQL::Types::Int, null: false,
description: 'ID of the Jira project.',
method: :id
field :name, GraphQL::STRING_TYPE, null: true,
field :name, GraphQL::Types::String, null: true,
description: 'Name of the Jira project.'
end
# rubocop:enable Graphql/AuthorizeTypes

View File

@ -9,11 +9,11 @@ module Types
present_using PrometheusAlertPresenter
field :id, GraphQL::ID_TYPE, null: false,
field :id, GraphQL::Types::ID, null: false,
description: 'ID of the alert condition.'
field :humanized_text,
GraphQL::STRING_TYPE,
GraphQL::Types::String,
null: false,
description: 'The human-readable text of the alert condition.'
end

View File

@ -7,7 +7,7 @@ module Ci
Ci::ExpirePipelineCacheService.new.execute(pipeline, delete: true)
pipeline.cancel_running if pipeline.cancelable? && ::Feature.enabled?(:cancel_pipelines_prior_to_destroy, default_enabled: :yaml)
pipeline.cancel_running if pipeline.cancelable? && ::Feature.enabled?(:cancel_pipelines_prior_to_destroy, pipeline.project, default_enabled: :yaml)
pipeline.reset.destroy!

View File

@ -2,16 +2,16 @@
= form_errors(@application_setting)
%fieldset
%p
= _("Add a Grafana button in the admin sidebar, monitoring section, to access a variety of statistics on the health and performance of GitLab.")
= link_to sprite_icon('question-o'), help_page_path('administration/monitoring/performance/grafana_configuration.md')
.form-group
.form-check
= f.check_box :grafana_enabled, class: 'form-check-input'
= f.label :grafana_enabled, class: 'form-check-label' do
= _('Enable access to Grafana')
= _("Add a link to Grafana")
.form-text.text-muted
= _("A Metrics Dashboard menu item appears in the Monitoring section of the Admin Area.")
.form-group
= f.label :grafana_url, _('Grafana URL'), class: 'label-bold'
= f.text_field :grafana_url, class: 'form-control gl-form-input', placeholder: '/-/grafana'
%span.form-text.text-muted#support_help_block= _('URL of the Grafana instance to link to from the Metrics Dashboard menu item.')
= f.submit _('Save changes'), class: "gl-button btn btn-confirm"

View File

@ -22,7 +22,9 @@
%button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Enable and configure Grafana.')
= _('Link to your Grafana instance.')
= link_to s_('Learn more.'), help_page_path('administration/monitoring/performance/grafana_configuration.md'), target: '_blank', rel: 'noopener noreferrer'
.settings-content
= render 'grafana'

View File

@ -65,12 +65,12 @@ GitLab sidebar:
1. On the top bar, select **Menu >** **{admin}** **Admin**.
1. On the left sidebar, select **Settings > Metrics and profiling**
and expand **Metrics - Grafana**.
1. Check the **Enable access to Grafana** checkbox.
1. Select the **Add a link to Grafana** checkbox.
1. Configure the **Grafana URL**:
- *If Grafana is enabled through Omnibus GitLab and on the same server,*
leave **Grafana URL** unchanged. It should be `/-/grafana`.
- *Otherwise,* enter the full URL of the Grafana instance.
1. Click **Save changes**.
1. Select **Save changes**.
GitLab displays your link in the **Menu > Admin > Monitoring > Metrics Dashboard**.

View File

@ -15,32 +15,32 @@ full list of reference architectures, see
> - **High Availability:** Yes ([Praefect](#configure-praefect-postgresql) needs a third-party PostgreSQL solution for HA)
> - **Test requests per second (RPS) rates:** API: 200 RPS, Web: 20 RPS, Git (Pull): 20 RPS, Git (Push): 4 RPS
| Service | Nodes | Configuration | GCP | AWS | Azure |
|--------------------------------------------|-------------|-------------------------|------------------|--------------|-----------|
| External load balancing node(3) | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Consul(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| PostgreSQL(1) | 3 | 8 vCPU, 30 GB memory | `n1-standard-8` | `m5.2xlarge` | `D8s v3` |
| PgBouncer(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Internal load balancing node(3) | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Redis - Cache(2) | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| Redis - Queues / Shared State(2) | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| Redis Sentinel - Cache(2) | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
| Redis Sentinel - Queues / Shared State(2) | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
| Gitaly | 3 | 16 vCPU, 60 GB memory | `n1-standard-16` | `m5.4xlarge` | `D16s v3` |
| Praefect | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Praefect PostgreSQL(1) | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| GitLab Rails | 3 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | `c5.9xlarge` | `F32s v2` |
| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
| Object storage(4) | n/a | n/a | n/a | n/a | n/a |
| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
| Service | Nodes | Configuration | GCP | AWS | Azure |
|-----------------------------------------------------|-------------|-------------------------|------------------|--------------|-----------|
| External load balancing node<sup>3</sup> | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Consul<sup>1</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| PostgreSQL<sup>1</sup> | 3 | 8 vCPU, 30 GB memory | `n1-standard-8` | `m5.2xlarge` | `D8s v3` |
| PgBouncer<sup>1</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Internal load balancing node<sup>3</sup> | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Redis - Cache<sup>2</sup> | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| Redis - Queues / Shared State<sup>2</sup> | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| Redis Sentinel - Cache<sup>2</sup> | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
| Redis Sentinel - Queues / Shared State<sup>2</sup> | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
| Gitaly | 3 | 16 vCPU, 60 GB memory | `n1-standard-16` | `m5.4xlarge` | `D16s v3` |
| Praefect | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Praefect PostgreSQL<sup>1</sup> | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| GitLab Rails | 3 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | `c5.9xlarge` | `F32s v2` |
| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
| Object storage<sup>4</sup> | n/a | n/a | n/a | n/a | n/a |
| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
4. Should be run on reputable third party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
4. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
<!-- markdownlint-enable MD029 -->
NOTE:
@ -141,7 +141,7 @@ is recommended instead of using NFS. Using an object storage service also
doesn't require you to provision and maintain a node.
It's also worth noting that at this time [Praefect requires its own database server](../gitaly/praefect.md#postgresql) and
that to achieve full High Availability a third party PostgreSQL database solution will be required.
that to achieve full High Availability a third-party PostgreSQL database solution will be required.
We hope to offer a built in solutions for these restrictions in the future but in the meantime a non HA PostgreSQL server
can be set up via Omnibus GitLab, which the above specs reflect. Refer to the following issues for more information: [`omnibus-gitlab#5919`](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5919) & [`gitaly#3398`](https://gitlab.com/gitlab-org/gitaly/-/issues/3398)
@ -2368,7 +2368,7 @@ in Kubernetes via our official [Helm Charts](https://docs.gitlab.com/charts/).
In this setup, we support running the equivalent of GitLab Rails and Sidekiq nodes
in a Kubernetes cluster, named Webservice and Sidekiq respectively. In addition,
the following other supporting services are supported: NGINX, Task Runner, Migrations,
Prometheus and Grafana.
Prometheus, and Grafana.
Hybrid installations leverage the benefits of both cloud native and traditional
compute deployments. With this, _stateless_ components can benefit from cloud native
@ -2379,23 +2379,23 @@ NOTE:
This is an **advanced** setup. Running services in Kubernetes is well known
to be complex. **This setup is only recommended** if you have strong working
knowledge and experience in Kubernetes. The rest of this
section will assume this.
section assumes this.
### Cluster topology
The following tables and diagram details the hybrid environment using the same formats
The following tables and diagram detail the hybrid environment using the same formats
as the normal environment above.
First starting with the components that run in Kubernetes. The recommendations at this
time use Google Clouds Kubernetes Engine (GKE) and associated machine types, but the memory
First are the components that run in Kubernetes. The recommendation at this time is to
use Google Clouds Kubernetes Engine (GKE) and associated machine types, but the memory
and CPU requirements should translate to most other providers. We hope to update this in the
future with further specific cloud provider details.
| Service | Nodes(1) | Configuration | GCP | Allocatable CPUs and Memory |
|-------------------------------------------------------|----------|-------------------------|------------------|-----------------------------|
| Webservice | 4 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | 127.5 vCPU, 118 GB memory |
| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | 15.5 vCPU, 50 GB memory |
| Supporting services such as NGINX or Prometheus | 2 | 4 vCPU, 15 GB memory | `n1-standard-4` | 7.75 vCPU, 25 GB memory |
| Service | Nodes<sup>1</sup> | Configuration | GCP | Allocatable CPUs and Memory |
|-------------------------------------------------------|-------------------|-------------------------|------------------|-----------------------------|
| Webservice | 4 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | 127.5 vCPU, 118 GB memory |
| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | 15.5 vCPU, 50 GB memory |
| Supporting services such as NGINX, Prometheus | 2 | 4 vCPU, 15 GB memory | `n1-standard-4` | 7.75 vCPU, 25 GB memory |
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
@ -2406,27 +2406,27 @@ future with further specific cloud provider details.
Next are the backend components that run on static compute VMs via Omnibus (or External PaaS
services where applicable):
| Service | Nodes | Configuration | GCP |
|--------------------------------------------|-------|-------------------------|------------------|
| Consul(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| PostgreSQL(1) | 3 | 8 vCPU, 30 GB memory | `n1-standard-8` |
| PgBouncer(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| Internal load balancing node(3) | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| Redis - Cache(2) | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` |
| Redis - Queues / Shared State(2) | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` |
| Redis Sentinel - Cache(2) | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` |
| Redis Sentinel - Queues / Shared State(2) | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` |
| Gitaly | 3 | 16 vCPU, 60 GB memory | `n1-standard-16` |
| Praefect | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| Praefect PostgreSQL(1) | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| Object storage(4) | n/a | n/a | n/a |
| Service | Nodes | Configuration | GCP |
|-----------------------------------------------------|-------|-------------------------|------------------|
| Consul<sup>1</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| PostgreSQL<sup>1</sup> | 3 | 8 vCPU, 30 GB memory | `n1-standard-8` |
| PgBouncer<sup>1</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| Internal load balancing node<sup>3</sup> | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| Redis - Cache<sup>2</sup> | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` |
| Redis - Queues / Shared State<sup>2</sup> | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` |
| Redis Sentinel - Cache<sup>2</sup> | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` |
| Redis Sentinel - Queues / Shared State<sup>2</sup> | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` |
| Gitaly | 3 | 16 vCPU, 60 GB memory | `n1-standard-16` |
| Praefect | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| Praefect PostgreSQL<sup>1</sup> | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| Object storage<sup>4</sup> | n/a | n/a | n/a |
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
4. Should be run on reputable third party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
4. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
<!-- markdownlint-enable MD029 -->
NOTE:
@ -2520,11 +2520,11 @@ documents how to apply the calculated configuration to the Helm Chart.
#### Webservice
Webservice pods typically need about 1 vCPU and 1.25 GB of memory _per worker_.
Each Webservice pod will consume roughly 4 vCPUs and 5 GB of memory using
Each Webservice pod consumes roughly 4 vCPUs and 5 GB of memory using
the [recommended topology](#cluster-topology) because four worker processes
are created by default and each pod has other small processes running.
For 10k users we recommend a total Puma worker count of around 80.
For 10,000 users we recommend a total Puma worker count of around 80.
With the [provided recommendations](#cluster-topology) this allows the deployment of up to 20
Webservice pods with 4 workers per pod and 5 pods per node. Expand available resources using
the ratio of 1 vCPU to 1.25 GB of memory _per each worker process_ for each additional

View File

@ -15,32 +15,32 @@ full list of reference architectures, see
> - **High Availability:** Yes ([Praefect](#configure-praefect-postgresql) needs a third-party PostgreSQL solution for HA)
> - **Test requests per second (RPS) rates:** API: 500 RPS, Web: 50 RPS, Git (Pull): 50 RPS, Git (Push): 10 RPS
| Service | Nodes | Configuration | GCP | AWS | Azure |
|------------------------------------------|-------------|-------------------------|------------------|--------------|-----------|
| External load balancing node(3) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
| Consul(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| PostgreSQL(1) | 3 | 16 vCPU, 60 GB memory | `n1-standard-16` | `m5.4xlarge` | `D16s v3` |
| PgBouncer(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Internal load balancing node(3) | 1 | 4 vCPU, 3.6GB memory | `n1-highcpu-4` | `c5.large` | `F2s v2` |
| Redis - Cache(2) | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| Redis - Queues / Shared State(2) | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| Redis Sentinel - Cache(2) | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
| Redis Sentinel - Queues / Shared State(2)| 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
| Gitaly | 3 | 32 vCPU, 120 GB memory | `n1-standard-32` | `m5.8xlarge` | `D32s v3` |
| Praefect | 3 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
| Praefect PostgreSQL(1) | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| GitLab Rails | 5 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | `c5.9xlarge` | `F32s v2` |
| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
| Object storage(4) | n/a | n/a | n/a | n/a | n/a |
| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
| Service | Nodes | Configuration | GCP | AWS | Azure |
|---------------------------------------------------|-------------|-------------------------|------------------|--------------|-----------|
| External load balancing node<sup>3</sup> | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
| Consul<sup>1</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| PostgreSQL<sup>1</sup> | 3 | 16 vCPU, 60 GB memory | `n1-standard-16` | `m5.4xlarge` | `D16s v3` |
| PgBouncer<sup>1</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Internal load balancing node<sup>3</sup> | 1 | 4 vCPU, 3.6GB memory | `n1-highcpu-4` | `c5.large` | `F2s v2` |
| Redis - Cache<sup>2</sup> | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| Redis - Queues / Shared State<sup>2</sup> | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| Redis Sentinel - Cache<sup>2</sup> | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
| Redis Sentinel - Queues / Shared State<sup>2</sup>| 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
| Gitaly | 3 | 32 vCPU, 120 GB memory | `n1-standard-32` | `m5.8xlarge` | `D32s v3` |
| Praefect | 3 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
| Praefect PostgreSQL<sup>1</sup> | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| GitLab Rails | 5 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | `c5.9xlarge` | `F32s v2` |
| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
| Object storage<sup>4</sup> | n/a | n/a | n/a | n/a | n/a |
| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
4. Should be run on reputable third party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
4. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
<!-- markdownlint-enable MD029 -->
NOTE:
@ -141,7 +141,7 @@ is recommended instead of using NFS. Using an object storage service also
doesn't require you to provision and maintain a node.
It's also worth noting that at this time [Praefect requires its own database server](../gitaly/praefect.md#postgresql) and
that to achieve full High Availability a third party PostgreSQL database solution will be required.
that to achieve full High Availability a third-party PostgreSQL database solution will be required.
We hope to offer a built in solutions for these restrictions in the future but in the meantime a non HA PostgreSQL server
can be set up via Omnibus GitLab, which the above specs reflect. Refer to the following issues for more information: [`omnibus-gitlab#5919`](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5919) & [`gitaly#3398`](https://gitlab.com/gitlab-org/gitaly/-/issues/3398)
@ -2380,7 +2380,7 @@ in Kubernetes via our official [Helm Charts](https://docs.gitlab.com/charts/).
In this setup, we support running the equivalent of GitLab Rails and Sidekiq nodes
in a Kubernetes cluster, named Webservice and Sidekiq respectively. In addition,
the following other supporting services are supported: NGINX, Task Runner, Migrations,
Prometheus and Grafana.
Prometheus, and Grafana.
Hybrid installations leverage the benefits of both cloud native and traditional
compute deployments. With this, _stateless_ components can benefit from cloud native
@ -2391,23 +2391,23 @@ NOTE:
This is an **advanced** setup. Running services in Kubernetes is well known
to be complex. **This setup is only recommended** if you have strong working
knowledge and experience in Kubernetes. The rest of this
section will assume this.
section assumes this.
### Cluster topology
The following tables and diagram details the hybrid environment using the same formats
The following tables and diagram detail the hybrid environment using the same formats
as the normal environment above.
First starting with the components that run in Kubernetes. The recommendations at this
time use Google Clouds Kubernetes Engine (GKE) and associated machine types, but the memory
First are the components that run in Kubernetes. The recommendation at this time is to
use Google Clouds Kubernetes Engine (GKE) and associated machine types, but the memory
and CPU requirements should translate to most other providers. We hope to update this in the
future with further specific cloud provider details.
| Service | Nodes(1) | Configuration | GCP | Allocatable CPUs and Memory |
|-------------------------------------------------------|----------|-------------------------|------------------|-----------------------------|
| Webservice | 7 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | 223 vCPU, 206.5 GB memory |
| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | 15.5 vCPU, 50 GB memory |
| Supporting services such as NGINX, Prometheus, etc. | 2 | 4 vCPU, 15 GB memory | `n1-standard-4` | 7.75 vCPU, 25 GB memory |
| Service | Nodes<sup>1</sup> | Configuration | GCP | Allocatable CPUs and Memory |
|-------------------------------------------------------|-------------------|-------------------------|------------------|-----------------------------|
| Webservice | 7 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | 223 vCPU, 206.5 GB memory |
| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | 15.5 vCPU, 50 GB memory |
| Supporting services such as NGINX, Prometheus | 2 | 4 vCPU, 15 GB memory | `n1-standard-4` | 7.75 vCPU, 25 GB memory |
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
@ -2418,27 +2418,27 @@ future with further specific cloud provider details.
Next are the backend components that run on static compute VMs via Omnibus (or External PaaS
services where applicable):
| Service | Nodes | Configuration | GCP |
|--------------------------------------------|-------|-------------------------|------------------|
| Consul(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| PostgreSQL(1) | 3 | 16 vCPU, 60 GB memory | `n1-standard-16` |
| PgBouncer(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| Internal load balancing node(3) | 1 | 4 vCPU, 3.6GB memory | `n1-highcpu-4` |
| Redis - Cache(2) | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` |
| Redis - Queues / Shared State(2) | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` |
| Redis Sentinel - Cache(2) | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` |
| Redis Sentinel - Queues / Shared State(2) | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` |
| Gitaly | 3 | 32 vCPU, 120 GB memory | `n1-standard-32` |
| Praefect | 3 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` |
| Praefect PostgreSQL(1) | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| Object storage(4) | n/a | n/a | n/a |
| Service | Nodes | Configuration | GCP |
|-----------------------------------------------------|-------|-------------------------|------------------|
| Consul<sup>1</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| PostgreSQL<sup>1</sup> | 3 | 16 vCPU, 60 GB memory | `n1-standard-16` |
| PgBouncer<sup>1</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| Internal load balancing node<sup>3</sup> | 1 | 4 vCPU, 3.6GB memory | `n1-highcpu-4` |
| Redis - Cache<sup>2</sup> | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` |
| Redis - Queues / Shared State<sup>2</sup> | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` |
| Redis Sentinel - Cache<sup>2</sup> | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` |
| Redis Sentinel - Queues / Shared State<sup>2</sup> | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` |
| Gitaly | 3 | 32 vCPU, 120 GB memory | `n1-standard-32` |
| Praefect | 3 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` |
| Praefect PostgreSQL<sup>1</sup> | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| Object storage<sup>4</sup> | n/a | n/a | n/a |
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
4. Should be run on reputable third party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
4. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
<!-- markdownlint-enable MD029 -->
NOTE:
@ -2532,11 +2532,11 @@ documents how to apply the calculated configuration to the Helm Chart.
#### Webservice
Webservice pods typically need about 1 vCPU and 1.25 GB of memory _per worker_.
Each Webservice pod will consume roughly 4 vCPUs and 5 GB of memory using
Each Webservice pod consumes roughly 4 vCPUs and 5 GB of memory using
the [recommended topology](#cluster-topology) because four worker processes
are created by default and each pod has other small processes running.
For 25k users we recommend a total Puma worker count of around 140.
For 25,000 users we recommend a total Puma worker count of around 140.
With the [provided recommendations](#cluster-topology) this allows the deployment of up to 35
Webservice pods with 4 workers per pod and 5 pods per node. Expand available resources using
the ratio of 1 vCPU to 1.25 GB of memory _per each worker process_ for each additional

View File

@ -18,20 +18,20 @@ For a full list of reference architectures, see
| Service | Nodes | Configuration | GCP | AWS | Azure |
|------------------------------------------|--------|-------------------------|-----------------|--------------|----------|
| Load balancer(3) | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| PostgreSQL(1) | 1 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
| Redis(2) | 1 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `m5.large` | `D2s v3` |
| Load balancer<sup>3</sup> | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| PostgreSQL<sup>1</sup> | 1 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
| Redis<sup>2</sup> | 1 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `m5.large` | `D2s v3` |
| Gitaly | 1 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| GitLab Rails | 2 | 8 vCPU, 7.2 GB memory | `n1-highcpu-8` | `c5.2xlarge` | `F8s v2` |
| Monitoring node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Object storage(4) | n/a | n/a | n/a | n/a | n/a |
| Object storage<sup>4</sup> | n/a | n/a | n/a | n/a | n/a |
| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
<!-- markdownlint-disable MD029 -->
1. Can be optionally run on reputable third party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run as reputable third party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Can be optionally run as reputable third party load balancing services (LB PaaS). AWS ELB is known to work.
4. Should be run on reputable third party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run as reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Can be optionally run as reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
4. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
<!-- markdownlint-enable MD029 -->
NOTE:

View File

@ -27,19 +27,19 @@ For a full list of reference architectures, see
| Service | Nodes | Configuration | GCP | AWS | Azure |
|--------------------------------------------|-------------|-----------------------|-----------------|--------------|----------|
| External load balancing node(3) | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Redis(2) | 3 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
| Consul(1) + Sentinel(2) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| PostgreSQL(1) | 3 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
| PgBouncer(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Internal load balancing node(3) | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| External load balancing node<sup>3</sup> | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Redis<sup>2</sup> | 3 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
| Consul<sup>1</sup> + Sentinel<sup>2</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| PostgreSQL<sup>1</sup> | 3 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
| PgBouncer<sup>1</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Internal load balancing node<sup>3</sup> | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Gitaly | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| Praefect | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Praefect PostgreSQL(1) | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Praefect PostgreSQL<sup>1</sup> | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Sidekiq | 4 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
| GitLab Rails | 3 | 8 vCPU, 7.2 GB memory | `n1-highcpu-8` | `c5.2xlarge` | `F8s v2` |
| Monitoring node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Object storage(4) | n/a | n/a | n/a | n/a | n/a |
| Object storage<sup>4</sup> | n/a | n/a | n/a | n/a | n/a |
| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
@ -47,7 +47,7 @@ For a full list of reference architectures, see
1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
4. Should be run on reputable third party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
4. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
<!-- markdownlint-enable MD029 -->
NOTE:
@ -63,10 +63,7 @@ together {
collections "**Sidekiq** x4" as sidekiq #ff8dd1
}
together {
card "**Prometheus + Grafana**" as monitor #7FFFD4
collections "**Consul** x3" as consul #e76a9b
}
card "**Prometheus + Grafana**" as monitor #7FFFD4
card "Gitaly Cluster" as gitaly_cluster {
collections "**Praefect** x3" as praefect #FF8C00
@ -86,14 +83,15 @@ card "Database" as database {
postgres_primary .[#4EA7FF]> postgres_secondary
}
card "redis" as redis {
collections "**Redis Persistent** x3" as redis_persistent #FF6347
collections "**Redis Cache** x3" as redis_cache #FF6347
collections "**Redis Persistent Sentinel** x3" as redis_persistent_sentinel #FF6347
collections "**Redis Cache Sentinel** x3"as redis_cache_sentinel #FF6347
card "**Consul + Sentinel**" as consul_sentinel {
collections "**Consul** x3" as consul #e76a9b
collections "**Redis Sentinel** x3" as sentinel #e6e727
}
redis_persistent <.[#FF6347]- redis_persistent_sentinel
redis_cache <.[#FF6347]- redis_cache_sentinel
card "Redis" as redis {
collections "**Redis** x3" as redis_nodes #FF6347
redis_nodes <.[#FF6347]- sentinel
}
cloud "**Object Storage**" as object_storage #white
@ -2097,6 +2095,184 @@ but with smaller performance requirements, several modifications can be consider
- As Redis Sentinel runs on the same box as Consul in this architecture, it may need to be run on a separate box if Redis is still being run via Omnibus.
- Redis: Can be run on reputable Cloud PaaS solutions such as Google Memorystore and AWS ElastiCache. In this setup, the Redis Sentinel is no longer required.
## Cloud Native Hybrid reference architecture with Helm Charts (alternative)
As an alternative approach, you can also run select components of GitLab as Cloud Native
in Kubernetes via our official [Helm Charts](https://docs.gitlab.com/charts/).
In this setup, we support running the equivalent of GitLab Rails and Sidekiq nodes
in a Kubernetes cluster, named Webservice and Sidekiq respectively. In addition,
the following other supporting services are supported: NGINX, Task Runner, Migrations,
Prometheus, and Grafana.
Hybrid installations leverage the benefits of both cloud native and traditional
compute deployments. With this, _stateless_ components can benefit from cloud native
workload management benefits while _stateful_ components are deployed in compute VMs
with Omnibus to benefit from increased permanence.
NOTE:
This is an **advanced** setup. Running services in Kubernetes is well known
to be complex. **This setup is only recommended** if you have strong working
knowledge and experience in Kubernetes. The rest of this
section assumes this.
### Cluster topology
The following tables and diagram detail the hybrid environment using the same formats
as the normal environment above.
First are the components that run in Kubernetes. The recommendation at this time is to
use Google Clouds Kubernetes Engine (GKE) and associated machine types, but the memory
and CPU requirements should translate to most other providers. We hope to update this in the
future with further specific cloud provider details.
| Service | Nodes<sup>1</sup> | Configuration | GCP | Allocatable CPUs and Memory |
|-------------------------------------------------------|-------------------|-------------------------|------------------|-----------------------------|
| Webservice | 2 | 16 vCPU, 14.4 GB memory | `n1-highcpu-16` | 31.8 vCPU, 24.8 GB memory |
| Sidekiq | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | 11.8 vCPU, 38.9 GB memory |
| Supporting services such as NGINX, Prometheus | 2 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | 3.9 vCPU, 11.8 GB memory |
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
1. Nodes configuration is shown as it is forced to ensure pod vcpu / memory ratios and avoid scaling during **performance testing**.
In production deployments there is no need to assign pods to nodes. A minimum of three nodes in three different availability zones is strongly recommended to align with resilient cloud architecture practices.
<!-- markdownlint-enable MD029 -->
Next are the backend components that run on static compute VMs via Omnibus (or External PaaS
services where applicable):
| Service | Nodes | Configuration | GCP |
|--------------------------------------------|-------|-------------------------|------------------|
| Redis<sup>2</sup> | 3 | 2 vCPU, 7.5 GB memory | `n1-standard-2` |
| Consul<sup>1</sup> + Sentinel<sup>2</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| PostgreSQL<sup>1</sup> | 3 | 2 vCPU, 7.5 GB memory | `n1-standard-2` |
| PgBouncer<sup>1</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| Internal load balancing node<sup>3</sup> | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| Gitaly | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` |
| Praefect | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| Praefect PostgreSQL<sup>1</sup> | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| Object storage<sup>4</sup> | n/a | n/a | n/a |
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
4. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
<!-- markdownlint-enable MD029 -->
NOTE:
For all PaaS solutions that involve configuring instances, it is strongly recommended to implement a minimum of three nodes in three different availability zones to align with resilient cloud architecture practices.
```plantuml
@startuml 3k
card "Kubernetes via Helm Charts" as kubernetes {
card "**External Load Balancer**" as elb #6a9be7
together {
collections "**Webservice** x2" as gitlab #32CD32
collections "**Sidekiq** x3" as sidekiq #ff8dd1
}
card "**Prometheus + Grafana**" as monitor #7FFFD4
card "**Supporting Services**" as support
}
card "**Internal Load Balancer**" as ilb #9370DB
card "**Consul + Sentinel**" as consul_sentinel {
collections "**Consul** x3" as consul #e76a9b
collections "**Redis Sentinel** x3" as sentinel #e6e727
}
card "Gitaly Cluster" as gitaly_cluster {
collections "**Praefect** x3" as praefect #FF8C00
collections "**Gitaly** x3" as gitaly #FF8C00
card "**Praefect PostgreSQL***\n//Non fault-tolerant//" as praefect_postgres #FF8C00
praefect -[#FF8C00]-> gitaly
praefect -[#FF8C00]> praefect_postgres
}
card "Database" as database {
collections "**PGBouncer** x3" as pgbouncer #4EA7FF
card "**PostgreSQL** (Primary)" as postgres_primary #4EA7FF
collections "**PostgreSQL** (Secondary) x2" as postgres_secondary #4EA7FF
pgbouncer -[#4EA7FF]-> postgres_primary
postgres_primary .[#4EA7FF]> postgres_secondary
}
card "Redis" as redis {
collections "**Redis** x3" as redis_nodes #FF6347
redis_nodes <.[#FF6347]- sentinel
}
cloud "**Object Storage**" as object_storage #white
elb -[#6a9be7]-> gitlab
elb -[#6a9be7]-> monitor
elb -[hidden]-> support
gitlab -[#32CD32]--> ilb
gitlab -[#32CD32]-> object_storage
gitlab -[#32CD32]---> redis
gitlab -[hidden]--> consul
sidekiq -[#ff8dd1]--> ilb
sidekiq -[#ff8dd1]-> object_storage
sidekiq -[#ff8dd1]---> redis
sidekiq -[hidden]--> consul
ilb -[#9370DB]-> gitaly_cluster
ilb -[#9370DB]-> database
consul .[#e76a9b]-> database
consul .[#e76a9b]-> gitaly_cluster
consul .[#e76a9b,norank]--> redis
monitor .[#7FFFD4]> consul
monitor .[#7FFFD4]-> database
monitor .[#7FFFD4]-> gitaly_cluster
monitor .[#7FFFD4,norank]--> redis
monitor .[#7FFFD4]> ilb
monitor .[#7FFFD4,norank]u--> elb
@enduml
```
### Resource usage settings
The following formulas help when calculating how many pods may be deployed within resource constraints.
The [3k reference architecture example values file](https://gitlab.com/gitlab-org/charts/gitlab/-/blob/master/examples/ref/3k.yaml)
documents how to apply the calculated configuration to the Helm Chart.
#### Webservice
Webservice pods typically need about 1 vCPU and 1.25 GB of memory _per worker_.
Each Webservice pod consumes roughly 4 vCPUs and 5 GB of memory using
the [recommended topology](#cluster-topology) because four worker processes
are created by default and each pod has other small processes running.
For 3,000 users we recommend a total Puma worker count of around 16.
With the [provided recommendations](#cluster-topology) this allows the deployment of up to 4
Webservice pods with 4 workers per pod and 2 pods per node. Expand available resources using
the ratio of 1 vCPU to 1.25 GB of memory _per each worker process_ for each additional
Webservice pod.
For further information on resource usage, see the [Webservice resources](https://docs.gitlab.com/charts/charts/gitlab/webservice/#resources).
#### Sidekiq
Sidekiq pods should generally have 1 vCPU and 2 GB of memory.
[The provided starting point](#cluster-topology) allows the deployment of up to
8 Sidekiq pods. Expand available resources using the 1 vCPU to 2GB memory
ratio for each additional pod.
For further information on resource usage, see the [Sidekiq resources](https://docs.gitlab.com/charts/charts/gitlab/sidekiq/#resources).
<div align="right">
<a type="button" class="btn btn-default" href="#setup-components">
Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i>

View File

@ -15,32 +15,32 @@ full list of reference architectures, see
> - **High Availability:** Yes ([Praefect](#configure-praefect-postgresql) needs a third-party PostgreSQL solution for HA)
> - **Test requests per second (RPS) rates:** API: 1000 RPS, Web: 100 RPS, Git (Pull): 100 RPS, Git (Push): 20 RPS
| Service | Nodes | Configuration | GCP | AWS | Azure |
|------------------------------------------|-------------|-------------------------|------------------|---------------|-----------|
| External load balancing node(3) | 1 | 8 vCPU, 7.2 GB memory | `n1-highcpu-8` | `c5.2xlarge` | `F8s v2` |
| Consul(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| PostgreSQL(1) | 3 | 32 vCPU, 120 GB memory | `n1-standard-32` | `m5.8xlarge` | `D32s v3` |
| PgBouncer(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Internal load balancing node(3) | 1 | 8 vCPU, 7.2 GB memory | `n1-highcpu-8` | `c5.2xlarge` | `F8s v2` |
| Redis - Cache(2) | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| Redis - Queues / Shared State(2) | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| Redis Sentinel - Cache(2) | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
| Redis Sentinel - Queues / Shared State(2)| 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
| Gitaly | 3 | 64 vCPU, 240 GB memory | `n1-standard-64` | `m5.16xlarge` | `D64s v3` |
| Praefect | 3 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
| Praefect PostgreSQL(1) | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| GitLab Rails | 12 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | `c5.9xlarge` | `F32s v2` |
| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
| Object storage(4) | n/a | n/a | n/a | n/a | n/a |
| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
| Service | Nodes | Configuration | GCP | AWS | Azure |
|---------------------------------------------------|-------------|-------------------------|------------------|---------------|-----------|
| External load balancing node<sup>3</sup> | 1 | 8 vCPU, 7.2 GB memory | `n1-highcpu-8` | `c5.2xlarge` | `F8s v2` |
| Consul<sup>1</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| PostgreSQL<sup>1</sup> | 3 | 32 vCPU, 120 GB memory | `n1-standard-32` | `m5.8xlarge` | `D32s v3` |
| PgBouncer<sup>1</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Internal load balancing node<sup>3</sup> | 1 | 8 vCPU, 7.2 GB memory | `n1-highcpu-8` | `c5.2xlarge` | `F8s v2` |
| Redis - Cache<sup>2</sup> | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| Redis - Queues / Shared State<sup>2</sup> | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| Redis Sentinel - Cache<sup>2</sup> | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
| Redis Sentinel - Queues / Shared State<sup>2</sup>| 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
| Gitaly | 3 | 64 vCPU, 240 GB memory | `n1-standard-64` | `m5.16xlarge` | `D64s v3` |
| Praefect | 3 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
| Praefect PostgreSQL<sup>1</sup> | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| GitLab Rails | 12 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | `c5.9xlarge` | `F32s v2` |
| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
| Object storage<sup>4</sup> | n/a | n/a | n/a | n/a | n/a |
| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
4. Should be run on reputable third party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
4. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
<!-- markdownlint-enable MD029 -->
NOTE:
@ -141,7 +141,7 @@ is recommended instead of using NFS. Using an object storage service also
doesn't require you to provision and maintain a node.
It's also worth noting that at this time [Praefect requires its own database server](../gitaly/praefect.md#postgresql) and
that to achieve full High Availability a third party PostgreSQL database solution will be required.
that to achieve full High Availability a third-party PostgreSQL database solution will be required.
We hope to offer a built in solutions for these restrictions in the future but in the meantime a non HA PostgreSQL server
can be set up via Omnibus GitLab, which the above specs reflect. Refer to the following issues for more information: [`omnibus-gitlab#5919`](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5919) & [`gitaly#3398`](https://gitlab.com/gitlab-org/gitaly/-/issues/3398)
@ -2391,7 +2391,7 @@ in Kubernetes via our official [Helm Charts](https://docs.gitlab.com/charts/).
In this setup, we support running the equivalent of GitLab Rails and Sidekiq nodes
in a Kubernetes cluster, named Webservice and Sidekiq respectively. In addition,
the following other supporting services are supported: NGINX, Task Runner, Migrations,
Prometheus and Grafana.
Prometheus, and Grafana.
Hybrid installations leverage the benefits of both cloud native and traditional
compute deployments. With this, _stateless_ components can benefit from cloud native
@ -2402,23 +2402,23 @@ NOTE:
This is an **advanced** setup. Running services in Kubernetes is well known
to be complex. **This setup is only recommended** if you have strong working
knowledge and experience in Kubernetes. The rest of this
section will assume this.
section assumes this.
### Cluster topology
The following tables and diagram details the hybrid environment using the same formats
The following tables and diagram detail the hybrid environment using the same formats
as the normal environment above.
First starting with the components that run in Kubernetes. The recommendations at this
time use Google Clouds Kubernetes Engine (GKE) and associated machine types, but the memory
First are the components that run in Kubernetes. The recommendation at this time is to
use Google Clouds Kubernetes Engine (GKE) and associated machine types, but the memory
and CPU requirements should translate to most other providers. We hope to update this in the
future with further specific cloud provider details.
| Service | Nodes(1) | Configuration | GCP | Allocatable CPUs and Memory |
|-------------------------------------------------------|----------|-------------------------|------------------|-----------------------------|
| Webservice | 16 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | 510 vCPU, 472 GB memory |
| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | 15.5 vCPU, 50 GB memory |
| Supporting services such as NGINX, Prometheus, etc. | 2 | 4 vCPU, 15 GB memory | `n1-standard-4` | 7.75 vCPU, 25 GB memory |
| Service | Nodes<sup>1</sup> | Configuration | GCP | Allocatable CPUs and Memory |
|-------------------------------------------------------|-------------------|-------------------------|------------------|-----------------------------|
| Webservice | 16 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | 510 vCPU, 472 GB memory |
| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | 15.5 vCPU, 50 GB memory |
| Supporting services such as NGINX, Prometheus | 2 | 4 vCPU, 15 GB memory | `n1-standard-4` | 7.75 vCPU, 25 GB memory |
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
@ -2429,27 +2429,27 @@ future with further specific cloud provider details.
Next are the backend components that run on static compute VMs via Omnibus (or External PaaS
services where applicable):
| Service | Nodes | Configuration | GCP |
|--------------------------------------------|-------|-------------------------|------------------|
| Consul(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| PostgreSQL(1) | 3 | 32 vCPU, 120 GB memory | `n1-standard-32` |
| PgBouncer(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| Internal load balancing node(3) | 1 | 8 vCPU, 7.2 GB memory | `n1-highcpu-8` |
| Redis - Cache(2) | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` |
| Redis - Queues / Shared State(2) | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` |
| Redis Sentinel - Cache(2) | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` |
| Redis Sentinel - Queues / Shared State(2) | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` |
| Gitaly | 3 | 64 vCPU, 240 GB memory | `n1-standard-64` |
| Praefect | 3 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` |
| Praefect PostgreSQL(1) | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| Object storage(4) | n/a | n/a | n/a |
| Service | Nodes | Configuration | GCP |
|-----------------------------------------------------|-------|-------------------------|------------------|
| Consul<sup>1</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| PostgreSQL<sup>1</sup> | 3 | 32 vCPU, 120 GB memory | `n1-standard-32` |
| PgBouncer<sup>1</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| Internal load balancing node<sup>3</sup> | 1 | 8 vCPU, 7.2 GB memory | `n1-highcpu-8` |
| Redis - Cache<sup>2</sup> | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` |
| Redis - Queues / Shared State<sup>2</sup> | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` |
| Redis Sentinel - Cache<sup>2</sup> | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` |
| Redis Sentinel - Queues / Shared State<sup>2</sup> | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` |
| Gitaly | 3 | 64 vCPU, 240 GB memory | `n1-standard-64` |
| Praefect | 3 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` |
| Praefect PostgreSQL<sup>1</sup> | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| Object storage<sup>4</sup> | n/a | n/a | n/a |
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
4. Should be run on reputable third party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
4. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
<!-- markdownlint-enable MD029 -->
NOTE:
@ -2543,11 +2543,11 @@ documents how to apply the calculated configuration to the Helm Chart.
#### Webservice
Webservice pods typically need about 1 vCPU and 1.25 GB of memory _per worker_.
Each Webservice pod will consume roughly 4 vCPUs and 5 GB of memory using
Each Webservice pod consumes roughly 4 vCPUs and 5 GB of memory using
the [recommended topology](#cluster-topology) because four worker processes
are created by default and each pod has other small processes running.
For 50k users we recommend a total Puma worker count of around 320.
For 50,000 users we recommend a total Puma worker count of around 320.
With the [provided recommendations](#cluster-topology) this allows the deployment of up to 80
Webservice pods with 4 workers per pod and 5 pods per node. Expand available resources using
the ratio of 1 vCPU to 1.25 GB of memory _per each worker process_ for each additional

View File

@ -24,19 +24,19 @@ costly-to-operate environment by using the
| Service | Nodes | Configuration | GCP | AWS | Azure |
|--------------------------------------------|-------------|-------------------------|-----------------|--------------|----------|
| External load balancing node(3) | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Redis(2) | 3 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
| Consul(1) + Sentinel(2) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| PostgreSQL(1) | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| PgBouncer(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Internal load balancing node(3) | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| External load balancing node<sup>3</sup> | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Redis<sup>2</sup> | 3 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
| Consul<sup>1</sup> + Sentinel<sup>2</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| PostgreSQL<sup>1</sup> | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| PgBouncer<sup>1</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Internal load balancing node<sup>3</sup> | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Gitaly | 3 | 8 vCPU, 30 GB memory | `n1-standard-8` | `m5.2xlarge` | `D8s v3` |
| Praefect | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Praefect PostgreSQL(1) | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Praefect PostgreSQL<sup>1</sup> | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Sidekiq | 4 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
| GitLab Rails | 3 | 16 vCPU, 14.4 GB memory | `n1-highcpu-16` | `c5.4xlarge` | `F16s v2`|
| Monitoring node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Object storage(4) | n/a | n/a | n/a | n/a | n/a |
| Object storage<sup>4</sup> | n/a | n/a | n/a | n/a | n/a |
| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
@ -44,7 +44,7 @@ costly-to-operate environment by using the
1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
4. Should be run on reputable third party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
4. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
<!-- markdownlint-enable MD029 -->
NOTE:
@ -80,9 +80,9 @@ card "Database" as database {
postgres_primary .[#4EA7FF]> postgres_secondary
}
node "**Consul + Sentinel** x3" as consul_sentinel {
component Consul as consul #e76a9b
component Sentinel as sentinel #e6e727
card "**Consul + Sentinel**" as consul_sentinel {
collections "**Consul** x3" as consul #e76a9b
collections "**Redis Sentinel** x3" as sentinel #e6e727
}
card "Redis" as redis {
@ -143,7 +143,7 @@ is recommended instead of using NFS. Using an object storage service also
doesn't require you to provision and maintain a node.
It's also worth noting that at this time [Praefect requires its own database server](../gitaly/praefect.md#postgresql) and
that to achieve full High Availability a third party PostgreSQL database solution will be required.
that to achieve full High Availability a third-party PostgreSQL database solution will be required.
We hope to offer a built in solutions for these restrictions in the future but in the meantime a non HA PostgreSQL server
can be set up via Omnibus GitLab, which the above specs reflect. Refer to the following issues for more information: [`omnibus-gitlab#5919`](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5919) & [`gitaly#3398`](https://gitlab.com/gitlab-org/gitaly/-/issues/3398)
@ -2072,7 +2072,7 @@ in Kubernetes via our official [Helm Charts](https://docs.gitlab.com/charts/).
In this setup, we support running the equivalent of GitLab Rails and Sidekiq nodes
in a Kubernetes cluster, named Webservice and Sidekiq respectively. In addition,
the following other supporting services are supported: NGINX, Task Runner, Migrations,
Prometheus and Grafana.
Prometheus, and Grafana.
Hybrid installations leverage the benefits of both cloud native and traditional
compute deployments. With this, _stateless_ components can benefit from cloud native
@ -2083,23 +2083,23 @@ NOTE:
This is an **advanced** setup. Running services in Kubernetes is well known
to be complex. **This setup is only recommended** if you have strong working
knowledge and experience in Kubernetes. The rest of this
section will assume this.
section assumes this.
### Cluster topology
The following tables and diagram details the hybrid environment using the same formats
The following tables and diagram detail the hybrid environment using the same formats
as the normal environment above.
First starting with the components that run in Kubernetes. The recommendations at this
time use Google Clouds Kubernetes Engine (GKE) and associated machine types, but the memory
First are the components that run in Kubernetes. The recommendation at this time is to
use Google Clouds Kubernetes Engine (GKE) and associated machine types, but the memory
and CPU requirements should translate to most other providers. We hope to update this in the
future with further specific cloud provider details.
| Service | Nodes(1) | Configuration | GCP | Allocatable CPUs and Memory |
|-------------------------------------------------------|----------|-------------------------|------------------|-----------------------------|
| Webservice | 5 | 16 vCPU, 14.4 GB memory | `n1-highcpu-16` | 79.5 vCPU, 62 GB memory |
| Sidekiq | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | 11.8 vCPU, 38.9 GB memory |
| Supporting services such as NGINX, Prometheus, etc. | 2 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | 3.9 vCPU, 11.8 GB memory |
| Service | Nodes<sup>1</sup> | Configuration | GCP | Allocatable CPUs and Memory |
|-------------------------------------------------------|-------------------|-------------------------|------------------|-----------------------------|
| Webservice | 5 | 16 vCPU, 14.4 GB memory | `n1-highcpu-16` | 79.5 vCPU, 62 GB memory |
| Sidekiq | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | 11.8 vCPU, 38.9 GB memory |
| Supporting services such as NGINX, Prometheus | 2 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | 3.9 vCPU, 11.8 GB memory |
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
@ -2112,22 +2112,22 @@ services where applicable):
| Service | Nodes | Configuration | GCP |
|--------------------------------------------|-------|-------------------------|------------------|
| Redis(2) | 3 | 2 vCPU, 7.5 GB memory | `n1-standard-2` |
| Consul(1) + Sentinel(2) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| PostgreSQL(1) | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` |
| PgBouncer(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| Internal load balancing node(3) | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| Redis<sup>2</sup> | 3 | 2 vCPU, 7.5 GB memory | `n1-standard-2` |
| Consul<sup>1</sup> + Sentinel<sup>2</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| PostgreSQL<sup>1</sup> | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` |
| PgBouncer<sup>1</sup> | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| Internal load balancing node<sup>3</sup> | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| Gitaly | 3 | 8 vCPU, 30 GB memory | `n1-standard-8` |
| Praefect | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| Praefect PostgreSQL(1) | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| Object storage(4) | n/a | n/a | n/a |
| Praefect PostgreSQL<sup>1</sup> | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| Object storage<sup>4</sup> | n/a | n/a | n/a |
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
4. Should be run on reputable third party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
4. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
<!-- markdownlint-enable MD029 -->
NOTE:
@ -2150,9 +2150,9 @@ card "Kubernetes via Helm Charts" as kubernetes {
card "**Internal Load Balancer**" as ilb #9370DB
node "**Consul + Sentinel** x3" as consul_sentinel {
component Consul as consul #e76a9b
component Sentinel as sentinel #e6e727
card "**Consul + Sentinel**" as consul_sentinel {
collections "**Consul** x3" as consul #e76a9b
collections "**Redis Sentinel** x3" as sentinel #e6e727
}
card "Gitaly Cluster" as gitaly_cluster {
@ -2221,11 +2221,11 @@ documents how to apply the calculated configuration to the Helm Chart.
#### Webservice
Webservice pods typically need about 1 vCPU and 1.25 GB of memory _per worker_.
Each Webservice pod will consume roughly 4 vCPUs and 5 GB of memory using
Each Webservice pod consumes roughly 4 vCPUs and 5 GB of memory using
the [recommended topology](#cluster-topology) because four worker processes
are created by default and each pod has other small processes running.
For 5k users we recommend a total Puma worker count of around 40.
For 5,000 users we recommend a total Puma worker count of around 40.
With the [provided recommendations](#cluster-topology) this allows the deployment of up to 10
Webservice pods with 4 workers per pod and 2 pods per node. Expand available resources using
the ratio of 1 vCPU to 1.25 GB of memory _per each worker process_ for each additional

View File

@ -71,6 +71,7 @@ The following reference architectures are available:
The following Cloud Native Hybrid reference architectures, where select recommended components can be run in Kubernetes, are available:
- [Up to 3,000 users](3k_users.md#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative)
- [Up to 5,000 users](5k_users.md#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative)
- [Up to 10,000 users](10k_users.md#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative)
- [Up to 25,000 users](25k_users.md#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative)

View File

@ -3836,7 +3836,7 @@ Count of License Scanning jobs run
Group: `group::composition analysis`
Data Category: `Subscription`
Data Category: `Operational`
Status: `data_available`

View File

@ -3,7 +3,7 @@
module Gitlab
module Ci
##
# Ci::Features is a class that aggregates all CI/CD feature flags in one place.
# Deprecated: Ci::Features is a class that aggregates all CI/CD feature flags in one place.
#
module Features
# NOTE: The feature flag `disallow_to_create_merge_request_pipelines_in_target_project`

View File

@ -352,11 +352,11 @@ module Gitlab
end
end
def self.dbname(ar_connection)
def self.db_config_name(ar_connection)
if ar_connection.respond_to?(:pool) &&
ar_connection.pool.respond_to?(:db_config) &&
ar_connection.pool.db_config.respond_to?(:database)
return ar_connection.pool.db_config.database
ar_connection.pool.db_config.respond_to?(:name)
return ar_connection.pool.db_config.name
end
'unknown'

View File

@ -74,9 +74,9 @@ module Gitlab
end
if Feature.enabled?(:multiple_database_metrics, default_enabled: :yaml)
::Gitlab::SafeRequestStore[:duration_by_database]&.each do |dbname, duration_by_role|
::Gitlab::SafeRequestStore[:duration_by_database]&.each do |name, duration_by_role|
duration_by_role.each do |db_role, duration|
payload[:"db_#{db_role}_#{dbname}_duration_s"] = duration.to_f.round(3)
payload[:"db_#{db_role}_#{name}_duration_s"] = duration.to_f.round(3)
end
end
end
@ -113,11 +113,11 @@ module Gitlab
::Gitlab::SafeRequestStore[duration_key] = (::Gitlab::SafeRequestStore[duration_key].presence || 0) + duration
# Per database metrics
dbname = ::Gitlab::Database.dbname(event.payload[:connection])
name = ::Gitlab::Database.db_config_name(event.payload[:connection])
::Gitlab::SafeRequestStore[:duration_by_database] ||= {}
::Gitlab::SafeRequestStore[:duration_by_database][dbname] ||= {}
::Gitlab::SafeRequestStore[:duration_by_database][dbname][db_role] ||= 0
::Gitlab::SafeRequestStore[:duration_by_database][dbname][db_role] += duration
::Gitlab::SafeRequestStore[:duration_by_database][name] ||= {}
::Gitlab::SafeRequestStore[:duration_by_database][name][db_role] ||= 0
::Gitlab::SafeRequestStore[:duration_by_database][name][db_role] += duration
end
def ignored_query?(payload)

View File

@ -177,7 +177,7 @@ module Gitlab
@app.call(env)
end
rescue UploadedFile::InvalidPathError => e
[400, { 'Content-Type' => 'text/plain' }, e.message]
[400, { 'Content-Type' => 'text/plain' }, [e.message]]
end
end
end

View File

@ -1405,6 +1405,9 @@ msgstr ""
msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
msgstr ""
msgid "A Metrics Dashboard menu item appears in the Monitoring section of the Admin Area."
msgstr ""
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr ""
@ -1897,9 +1900,6 @@ msgstr ""
msgid "Add a GPG key"
msgstr ""
msgid "Add a Grafana button in the admin sidebar, monitoring section, to access a variety of statistics on the health and performance of GitLab."
msgstr ""
msgid "Add a Jaeger URL to replace this page with a link to your Jaeger server. You first need to %{link_start_tag}install Jaeger%{link_end_tag}."
msgstr ""
@ -1936,6 +1936,9 @@ msgstr ""
msgid "Add a link"
msgstr ""
msgid "Add a link to Grafana"
msgstr ""
msgid "Add a new issue"
msgstr ""
@ -12085,18 +12088,12 @@ msgstr ""
msgid "Enable a Prometheus metrics endpoint at %{metrics_path} to expose a variety of statistics on the health and performance of GitLab. Additional information on authenticating and connecting to the metrics endpoint is available %{link}."
msgstr ""
msgid "Enable access to Grafana"
msgstr ""
msgid "Enable access to the Performance Bar"
msgstr ""
msgid "Enable access to the Performance Bar for a given group."
msgstr ""
msgid "Enable and configure Grafana."
msgstr ""
msgid "Enable and configure Prometheus metrics."
msgstr ""
@ -19637,6 +19634,9 @@ msgstr ""
msgid "Link to go to GitLab pipeline documentation"
msgstr ""
msgid "Link to your Grafana instance."
msgstr ""
msgid "Linked emails (%{email_count})"
msgstr ""
@ -22360,9 +22360,6 @@ msgstr ""
msgid "Not confidential"
msgstr ""
msgid "Not enough data"
msgstr ""
msgid "Not found."
msgstr ""
@ -34794,6 +34791,9 @@ msgstr ""
msgid "URL must start with %{codeStart}http://%{codeEnd}, %{codeStart}https://%{codeEnd}, or %{codeStart}ftp://%{codeEnd}"
msgstr ""
msgid "URL of the Grafana instance to link to from the Metrics Dashboard menu item."
msgstr ""
msgid "URL of the external Spam Check endpoint"
msgstr ""

View File

@ -3,7 +3,7 @@
import MockAdapter from 'axios-mock-adapter';
import $ from 'jquery';
import { setTestTimeout } from 'helpers/timeout';
import BlobViewer from '~/blob/viewer/index';
import { BlobViewer } from '~/blob/viewer/index';
import axios from '~/lib/utils/axios_utils';
const execImmediately = (callback) => {

View File

@ -1,152 +0,0 @@
import { mount, shallowMount } from '@vue/test-utils';
import StageNavItem from '~/cycle_analytics/components/stage_nav_item.vue';
describe('StageNavItem', () => {
let wrapper = null;
const title = 'Cool stage';
const value = '1 day';
function createComponent(props, shallow = true) {
const func = shallow ? shallowMount : mount;
return func(StageNavItem, {
propsData: {
isActive: false,
isUserAllowed: false,
isDefaultStage: true,
title,
value,
...props,
},
});
}
function hasStageName() {
const stageName = wrapper.find('.stage-name');
expect(stageName.exists()).toBe(true);
expect(stageName.text()).toEqual(title);
}
it('renders stage name', () => {
wrapper = createComponent({ isUserAllowed: true });
hasStageName();
wrapper.destroy();
});
describe('User has access', () => {
describe('with a value', () => {
beforeEach(() => {
wrapper = createComponent({ isUserAllowed: true });
});
afterEach(() => {
wrapper.destroy();
});
it('renders the value for median value', () => {
expect(wrapper.find('.stage-empty').exists()).toBe(false);
expect(wrapper.find('.not-available').exists()).toBe(false);
expect(wrapper.find('.stage-median').text()).toEqual(value);
});
});
describe('without a value', () => {
beforeEach(() => {
wrapper = createComponent({ isUserAllowed: true, value: null });
});
afterEach(() => {
wrapper.destroy();
});
it('has the stage-empty class', () => {
expect(wrapper.find('.stage-empty').exists()).toBe(true);
});
it('renders Not enough data for the median value', () => {
expect(wrapper.find('.stage-median').text()).toEqual('Not enough data');
});
});
});
describe('is active', () => {
beforeEach(() => {
wrapper = createComponent({ isActive: true }, false);
});
afterEach(() => {
wrapper.destroy();
});
it('has the active class', () => {
expect(wrapper.find('.stage-nav-item').classes('active')).toBe(true);
});
});
describe('is not active', () => {
beforeEach(() => {
wrapper = createComponent();
});
afterEach(() => {
wrapper.destroy();
});
it('emits the `select` event when clicked', () => {
expect(wrapper.emitted().select).toBeUndefined();
wrapper.trigger('click');
return wrapper.vm.$nextTick(() => {
expect(wrapper.emitted().select.length).toBe(1);
});
});
});
describe('User does not have access', () => {
beforeEach(() => {
wrapper = createComponent({ isUserAllowed: false }, false);
});
afterEach(() => {
wrapper.destroy();
});
it('renders stage name', () => {
hasStageName();
});
it('has class not-available', () => {
expect(wrapper.find('.stage-empty').exists()).toBe(false);
expect(wrapper.find('.not-available').exists()).toBe(true);
});
it('renders Not available for the median value', () => {
expect(wrapper.find('.stage-median').text()).toBe('Not available');
});
it('does not render options menu', () => {
expect(wrapper.find('[data-testid="more-actions-toggle"]').exists()).toBe(false);
});
});
describe('User can edit stages', () => {
beforeEach(() => {
wrapper = createComponent({ isUserAllowed: true }, false);
});
afterEach(() => {
wrapper.destroy();
});
it('renders stage name', () => {
hasStageName();
});
it('does not render options menu', () => {
expect(wrapper.find('[data-testid="more-actions-toggle"]').exists()).toBe(false);
});
it('can not edit the stage', () => {
expect(wrapper.text()).not.toContain('Edit stage');
});
it('can not remove the stage', () => {
expect(wrapper.text()).not.toContain('Remove stage');
});
it('can not hide the stage', () => {
expect(wrapper.text()).not.toContain('Hide stage');
});
});
});

View File

@ -1,6 +1,5 @@
import { useFakeDate } from 'helpers/fake_date';
import {
decorateEvents,
decorateData,
transformStagesForPathNavigation,
timeSummaryForPathNavigation,
@ -13,7 +12,6 @@ import {
selectedStage,
rawData,
convertedData,
rawEvents,
allowedStages,
stageMedians,
pathNavIssueMetric,
@ -21,34 +19,6 @@ import {
} from './mock_data';
describe('Value stream analytics utils', () => {
describe('decorateEvents', () => {
const [result] = decorateEvents(rawEvents, selectedStage);
const eventKeys = Object.keys(result);
const authorKeys = Object.keys(result.author);
it('will return the same number of events', () => {
expect(decorateEvents(rawEvents, selectedStage).length).toBe(rawEvents.length);
});
it('will set all the required event fields', () => {
['totalTime', 'author', 'createdAt', 'shortSha', 'commitUrl'].forEach((key) => {
expect(eventKeys).toContain(key);
});
['webUrl', 'avatarUrl'].forEach((key) => {
expect(authorKeys).toContain(key);
});
});
it('will remove unused fields', () => {
['total_time', 'created_at', 'short_sha', 'commit_url'].forEach((key) => {
expect(eventKeys).not.toContain(key);
});
['web_url', 'avatar_url'].forEach((key) => {
expect(authorKeys).not.toContain(key);
});
});
});
describe('decorateData', () => {
const result = decorateData(rawData);
it('returns the summary data', () => {

View File

@ -255,7 +255,7 @@ RSpec.describe Types::GlobalIDType do
query(GraphQL.parse(gql_query), vars).result
end
all_types = [::GraphQL::ID_TYPE, ::Types::GlobalIDType, ::Types::GlobalIDType[::Project]]
all_types = [::GraphQL::Types::ID, ::Types::GlobalIDType, ::Types::GlobalIDType[::Project]]
shared_examples 'a working query' do
# Simplified schema to test compatibility
@ -284,7 +284,7 @@ RSpec.describe Types::GlobalIDType do
# This is needed so that all types are always registered as input types
field :echo, String, null: true do
argument :id, ::GraphQL::ID_TYPE, required: false
argument :id, ::GraphQL::Types::ID, required: false
argument :gid, ::Types::GlobalIDType, required: false
argument :pid, ::Types::GlobalIDType[::Project], required: false
end

View File

@ -36,7 +36,7 @@ RSpec.describe Types::PermissionTypes::BasePermissionType do
expected_keywords = {
name: :resolve_using_hash,
hash_key: :the_key,
type: GraphQL::BOOLEAN_TYPE,
type: GraphQL::Types::Boolean,
description: "custom description",
null: false
}

View File

@ -487,19 +487,19 @@ RSpec.describe Gitlab::Database do
end
end
describe '.dbname' do
it 'returns the dbname for the connection' do
describe '.db_config_name' do
it 'returns the db_config name for the connection' do
connection = ActiveRecord::Base.connection
expect(described_class.dbname(connection)).to be_a(String)
expect(described_class.dbname(connection)).to eq(connection.pool.db_config.database)
expect(described_class.db_config_name(connection)).to be_a(String)
expect(described_class.db_config_name(connection)).to eq(connection.pool.db_config.name)
end
context 'when the pool is a NullPool' do
it 'returns unknown' do
connection = double(:active_record_connection, pool: ActiveRecord::ConnectionAdapters::NullPool.new)
expect(described_class.dbname(connection)).to eq('unknown')
expect(described_class.db_config_name(connection)).to eq('unknown')
end
end
end

View File

@ -77,7 +77,8 @@ RSpec.describe Gitlab::Middleware::Multipart do
result = subject
expect(result[0]).to eq(400)
expect(result[2]).to include('insecure path used')
expect(result[2]).to be_a(Array)
expect(result[2].first).to include('insecure path used')
end
end
end

View File

@ -23,7 +23,7 @@ RSpec.describe Gitlab::ObjectHierarchy do
end
it 'can find ancestors upto a certain level' do
relation = described_class.new(Group.where(id: child2), options: options).base_and_ancestors(upto: child1)
relation = described_class.new(Group.where(id: child2), options: options).base_and_ancestors(upto: child1.id)
expect(relation).to contain_exactly(child2)
end
@ -143,7 +143,7 @@ RSpec.describe Gitlab::ObjectHierarchy do
end
it 'can find ancestors upto a certain level' do
relation = described_class.new(Group.where(id: child2), options: options).ancestors(upto: child1)
relation = described_class.new(Group.where(id: child2), options: options).ancestors(upto: child1.id)
expect(relation).to be_empty
end

View File

@ -298,7 +298,7 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
allow(Gitlab::Database::LoadBalancing).to receive(:enable?).and_return(true)
end
let(:dbname) { ::Gitlab::Database.dbname(ActiveRecord::Base.connection) }
let(:db_config_name) { ::Gitlab::Database.db_config_name(ActiveRecord::Base.connection) }
let(:expected_end_payload_with_db) do
expected_end_payload.merge(
@ -314,7 +314,7 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
'db_primary_cached_count' => 0,
'db_primary_wal_count' => 0,
'db_primary_duration_s' => a_value > 0,
"db_primary_#{dbname}_duration_s" => a_value > 0,
"db_primary_#{db_config_name}_duration_s" => a_value > 0,
'db_primary_wal_cached_count' => 0,
'db_replica_wal_cached_count' => 0
)

View File

@ -23,7 +23,7 @@ RSpec.shared_examples 'store ActiveRecord info in RequestStore' do |db_role|
db_replica_wal_cached_count: 0,
db_replica_wal_count: 0
}
expected[:"db_primary_#{::Gitlab::Database.dbname(connection)}_duration_s"] = 0.002 if record_query
expected[:"db_primary_#{::Gitlab::Database.db_config_name(connection)}_duration_s"] = 0.002 if record_query
elsif db_role == :replica
expected = {
db_count: record_query ? 1 : 0,
@ -40,7 +40,7 @@ RSpec.shared_examples 'store ActiveRecord info in RequestStore' do |db_role|
db_primary_wal_cached_count: 0,
db_primary_wal_count: 0
}
expected[:"db_replica_#{::Gitlab::Database.dbname(connection)}_duration_s"] = 0.002 if record_query
expected[:"db_replica_#{::Gitlab::Database.db_config_name(connection)}_duration_s"] = 0.002 if record_query
else
expected = {
db_count: record_query ? 1 : 0,
@ -64,7 +64,7 @@ RSpec.shared_examples 'store ActiveRecord info in RequestStore' do |db_role|
subscriber.sql(event)
connection = event.payload[:connection]
expect(described_class.db_counter_payload).not_to include(:"db_replica_#{::Gitlab::Database.dbname(connection)}_duration_s")
expect(described_class.db_counter_payload).not_to include(:"db_replica_#{::Gitlab::Database.db_config_name(connection)}_duration_s")
end
end
end

Some files were not shown because too many files have changed in this diff Show More