Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
6eb3540d3d
commit
8e0dafbb66
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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> ·
|
||||
<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>
|
|
@ -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> ·
|
||||
<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>
|
|
@ -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>
|
|
@ -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> ·
|
||||
<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>
|
|
@ -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>
|
|
@ -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> ·
|
||||
<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>
|
|
@ -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: '',
|
||||
},
|
||||
},
|
||||
};
|
|
@ -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) {
|
||||
|
|
|
@ -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 });
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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.'
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.'
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.'
|
||||
|
||||
|
|
|
@ -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],
|
||||
|
|
|
@ -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],
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.'
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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.'
|
||||
|
|
|
@ -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.'
|
||||
|
|
|
@ -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.'
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.'
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.'
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.'
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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?
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.'
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.'
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.'
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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!
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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'
|
||||
|
||||
|
|
|
@ -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**.
|
||||
|
||||
|
|
|
@ -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 Cloud’s 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 Cloud’s 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
|
||||
|
|
|
@ -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 Cloud’s 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 Cloud’s 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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 Cloud’s 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>
|
||||
|
|
|
@ -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 Cloud’s 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 Cloud’s 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
|
||||
|
|
|
@ -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 Cloud’s 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 Cloud’s 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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -3836,7 +3836,7 @@ Count of License Scanning jobs run
|
|||
|
||||
Group: `group::composition analysis`
|
||||
|
||||
Data Category: `Subscription`
|
||||
Data Category: `Operational`
|
||||
|
||||
Status: `data_available`
|
||||
|
||||
|
|
|
@ -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`
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ""
|
||||
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -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', () => {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue