Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
85f7fa54f4
commit
bfce95a4c5
|
@ -1 +1 @@
|
|||
397a8aa41c8b1b159a667fb262aebc644719e074
|
||||
14370f86aaddaf173ff205148704eab118d8d181
|
||||
|
|
|
@ -6,6 +6,7 @@ import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
|
|||
import Badge from './badge.vue';
|
||||
import BadgeForm from './badge_form.vue';
|
||||
import BadgeList from './badge_list.vue';
|
||||
import { GlSprintf } from '@gitlab/ui';
|
||||
|
||||
export default {
|
||||
name: 'BadgeSettings',
|
||||
|
@ -14,14 +15,15 @@ export default {
|
|||
BadgeForm,
|
||||
BadgeList,
|
||||
GlModal: DeprecatedModal2,
|
||||
GlSprintf,
|
||||
},
|
||||
i18n: {
|
||||
deleteModalText: s__(
|
||||
'Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored.',
|
||||
),
|
||||
},
|
||||
computed: {
|
||||
...mapState(['badgeInModal', 'isEditing']),
|
||||
deleteModalText() {
|
||||
return s__(
|
||||
'Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored.',
|
||||
);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['deleteBadge']),
|
||||
|
@ -54,7 +56,13 @@ export default {
|
|||
:link-url="badgeInModal ? badgeInModal.renderedLinkUrl : ''"
|
||||
/>
|
||||
</div>
|
||||
<p v-html="deleteModalText"></p>
|
||||
<p>
|
||||
<gl-sprintf :message="$options.i18n.deleteModalText">
|
||||
<template #strong="{ content }">
|
||||
<strong>{{ content }}</strong>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</p>
|
||||
</gl-modal>
|
||||
|
||||
<badge-form v-show="isEditing" :is-editing="true" />
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import { escape } from 'lodash';
|
||||
import { GlModal, GlButton, GlDeprecatedButton, GlFormInput } from '@gitlab/ui';
|
||||
import { GlModal, GlButton, GlDeprecatedButton, GlFormInput, GlSprintf } from '@gitlab/ui';
|
||||
import SplitButton from '~/vue_shared/components/split_button.vue';
|
||||
import { s__, sprintf } from '~/locale';
|
||||
import csrf from '~/lib/utils/csrf';
|
||||
|
@ -30,6 +30,7 @@ export default {
|
|||
GlButton,
|
||||
GlDeprecatedButton,
|
||||
GlFormInput,
|
||||
GlSprintf,
|
||||
},
|
||||
props: {
|
||||
clusterPath: {
|
||||
|
@ -67,18 +68,6 @@ export default {
|
|||
)
|
||||
: s__('ClusterIntegration|You are about to remove your cluster integration.');
|
||||
},
|
||||
warningToBeRemoved() {
|
||||
return s__(`ClusterIntegration|
|
||||
This will permanently delete the following resources:
|
||||
<ul>
|
||||
<li>All installed applications and related resources</li>
|
||||
<li>The <code>gitlab-managed-apps</code> namespace</li>
|
||||
<li>Any project namespaces</li>
|
||||
<li><code>clusterroles</code></li>
|
||||
<li><code>clusterrolebindings</code></li>
|
||||
</ul>
|
||||
`);
|
||||
},
|
||||
confirmationTextLabel() {
|
||||
return sprintf(
|
||||
this.confirmCleanup
|
||||
|
@ -144,7 +133,27 @@ export default {
|
|||
>
|
||||
<template>
|
||||
<p>{{ warningMessage }}</p>
|
||||
<div v-if="confirmCleanup" v-html="warningToBeRemoved"></div>
|
||||
<div v-if="confirmCleanup">
|
||||
{{ s__('ClusterIntegration|This will permanently delete the following resources:') }}
|
||||
<ul>
|
||||
<li>
|
||||
{{ s__('ClusterIntegration|All installed applications and related resources') }}
|
||||
</li>
|
||||
<li>
|
||||
<gl-sprintf :message="s__('ClusterIntegration|The %{gitlabNamespace} namespace')">
|
||||
<template #gitlabNamespace>
|
||||
<!-- eslint-disable-next-line @gitlab/vue-require-i18n-strings -->
|
||||
<code>{{ 'gitlab-managed-apps' }}</code>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</li>
|
||||
<li>{{ s__('ClusterIntegration|Any project namespaces') }}</li>
|
||||
<!-- eslint-disable @gitlab/vue-require-i18n-strings -->
|
||||
<li><code>clusterroles</code></li>
|
||||
<li><code>clusterrolebindings</code></li>
|
||||
<!-- eslint-enable @gitlab/vue-require-i18n-strings -->
|
||||
</ul>
|
||||
</div>
|
||||
<strong v-html="confirmationTextLabel"></strong>
|
||||
<form ref="form" :action="clusterPath" method="post" class="gl-mb-5">
|
||||
<input ref="method" type="hidden" name="_method" value="delete" />
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
<script>
|
||||
import { escape } from 'lodash';
|
||||
import { mapState, mapGetters, mapActions } from 'vuex';
|
||||
import { s__, sprintf } from '~/locale';
|
||||
import { s__ } from '~/locale';
|
||||
import { GlSprintf, GlLink } from '@gitlab/ui';
|
||||
|
||||
import gkeDropdownMixin from './gke_dropdown_mixin';
|
||||
|
||||
export default {
|
||||
name: 'GkeProjectIdDropdown',
|
||||
components: {
|
||||
GlSprintf,
|
||||
GlLink,
|
||||
},
|
||||
mixins: [gkeDropdownMixin],
|
||||
props: {
|
||||
docsUrl: {
|
||||
|
@ -46,31 +50,23 @@ export default {
|
|||
return s__('ClusterIntegration|Select project');
|
||||
},
|
||||
helpText() {
|
||||
let message;
|
||||
if (this.hasErrors) {
|
||||
return this.errorMessage;
|
||||
}
|
||||
|
||||
if (!this.items) {
|
||||
message =
|
||||
'ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}.';
|
||||
return s__(
|
||||
'ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}.',
|
||||
);
|
||||
}
|
||||
|
||||
message =
|
||||
this.items && this.items.length
|
||||
? 'ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}.'
|
||||
: 'ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}.';
|
||||
|
||||
return sprintf(
|
||||
s__(message),
|
||||
{
|
||||
docsLinkEnd: ' <i class="fa fa-external-link" aria-hidden="true"></i></a>',
|
||||
docsLinkStart: `<a href="${escape(
|
||||
this.docsUrl,
|
||||
)}" target="_blank" rel="noopener noreferrer">`,
|
||||
},
|
||||
false,
|
||||
);
|
||||
return this.items.length
|
||||
? s__(
|
||||
'ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}.',
|
||||
)
|
||||
: s__(
|
||||
'ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}.',
|
||||
);
|
||||
},
|
||||
errorMessage() {
|
||||
if (!this.projectHasBillingEnabled) {
|
||||
|
@ -80,21 +76,13 @@ export default {
|
|||
);
|
||||
}
|
||||
|
||||
return sprintf(
|
||||
s__(
|
||||
'This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target="_blank" rel="noopener noreferrer">enable billing <i class="fa fa-external-link" aria-hidden="true"></i></a> and try again.',
|
||||
),
|
||||
{
|
||||
linkToBilling:
|
||||
'https://console.cloud.google.com/freetrial?utm_campaign=2018_cpanel&utm_source=gitlab&utm_medium=referral',
|
||||
},
|
||||
false,
|
||||
return s__(
|
||||
'ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again.',
|
||||
);
|
||||
}
|
||||
|
||||
return sprintf(
|
||||
s__('ClusterIntegration|An error occurred while trying to fetch your projects: %{error}'),
|
||||
{ error: this.gapiError },
|
||||
return s__(
|
||||
'ClusterIntegration|An error occurred while trying to fetch your projects: %{error}',
|
||||
);
|
||||
},
|
||||
},
|
||||
|
@ -182,7 +170,28 @@ export default {
|
|||
'text-muted': !hasErrors,
|
||||
}"
|
||||
class="form-text"
|
||||
v-html="helpText"
|
||||
></span>
|
||||
>
|
||||
<gl-sprintf :message="helpText">
|
||||
<template #linkToBilling="{ content }">
|
||||
<gl-link
|
||||
:href="
|
||||
'https://console.cloud.google.com/freetrial?utm_campaign=2018_cpanel&utm_source=gitlab&utm_medium=referral'
|
||||
"
|
||||
target="_blank"
|
||||
>{{ content }} <i class="fa fa-external-link" aria-hidden="true"></i
|
||||
></gl-link>
|
||||
</template>
|
||||
|
||||
<template #docsLink="{ content }">
|
||||
<gl-link :href="docsUrl" target="_blank"
|
||||
>{{ content }} <i class="fa fa-external-link" aria-hidden="true"></i
|
||||
></gl-link>
|
||||
</template>
|
||||
|
||||
<template #error>
|
||||
{{ gapiError }}
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -21,7 +21,7 @@ export const EMPTY_RUNNERS = __(
|
|||
'Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}',
|
||||
);
|
||||
export const ERROR_CONFIG = __(
|
||||
'Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}',
|
||||
'Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}',
|
||||
);
|
||||
export const ERROR_PERMISSION = __(
|
||||
'You do not have permission to run the Web Terminal. Please contact a project administrator.',
|
||||
|
@ -34,6 +34,8 @@ export const configCheckError = (status, helpUrl) => {
|
|||
{
|
||||
helpStart: `<a href="${escape(helpUrl)}" target="_blank">`,
|
||||
helpEnd: '</a>',
|
||||
codeStart: '<code>',
|
||||
codeEnd: '</code>',
|
||||
},
|
||||
false,
|
||||
);
|
||||
|
|
|
@ -1,5 +1,2 @@
|
|||
/* eslint-disable @gitlab/require-i18n-strings */
|
||||
|
||||
export const ESC_KEY = 'Escape';
|
||||
export const ESC_KEY_IE11 = 'Esc'; // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
|
||||
export const ENTER_KEY = 'Enter';
|
||||
|
|
|
@ -7,8 +7,8 @@ import {
|
|||
GlButtonGroup,
|
||||
GlFormGroup,
|
||||
GlFormInput,
|
||||
GlDeprecatedDropdown,
|
||||
GlDeprecatedDropdownItem,
|
||||
GlNewDropdown as GlDropdown,
|
||||
GlNewDropdownItem as GlDropdownItem,
|
||||
GlModal,
|
||||
GlTooltipDirective,
|
||||
} from '@gitlab/ui';
|
||||
|
@ -40,8 +40,8 @@ export default {
|
|||
GlButtonGroup,
|
||||
GlFormGroup,
|
||||
GlFormInput,
|
||||
GlDeprecatedDropdown,
|
||||
GlDeprecatedDropdownItem,
|
||||
GlDropdown,
|
||||
GlDropdownItem,
|
||||
GlModal,
|
||||
GlLink,
|
||||
Icon,
|
||||
|
@ -251,20 +251,20 @@ export default {
|
|||
</template>
|
||||
</gl-form-group>
|
||||
<gl-form-group v-else label-for="alert-query-dropdown" :label="$options.alertQueryText.label">
|
||||
<gl-deprecated-dropdown
|
||||
<gl-dropdown
|
||||
id="alert-query-dropdown"
|
||||
:text="queryDropdownLabel"
|
||||
toggle-class="dropdown-menu-toggle qa-alert-query-dropdown"
|
||||
toggle-class="dropdown-menu-toggle gl-border-1! qa-alert-query-dropdown"
|
||||
>
|
||||
<gl-deprecated-dropdown-item
|
||||
<gl-dropdown-item
|
||||
v-for="query in relevantQueries"
|
||||
:key="query.metricId"
|
||||
data-qa-selector="alert_query_option"
|
||||
@click="selectQuery(query.metricId)"
|
||||
>
|
||||
{{ query.label }}
|
||||
</gl-deprecated-dropdown-item>
|
||||
</gl-deprecated-dropdown>
|
||||
</gl-dropdown-item>
|
||||
</gl-dropdown>
|
||||
</gl-form-group>
|
||||
<gl-button-group class="mb-3" :label="s__('PrometheusAlerts|Operator')">
|
||||
<gl-deprecated-button
|
||||
|
|
|
@ -7,7 +7,7 @@ import DashboardHeader from './dashboard_header.vue';
|
|||
import DashboardPanel from './dashboard_panel.vue';
|
||||
import { s__ } from '~/locale';
|
||||
import createFlash from '~/flash';
|
||||
import { ESC_KEY, ESC_KEY_IE11 } from '~/lib/utils/keys';
|
||||
import { ESC_KEY } from '~/lib/utils/keys';
|
||||
import { mergeUrlParams, updateHistory } from '~/lib/utils/url_utility';
|
||||
import invalidUrl from '~/lib/utils/invalid_url';
|
||||
import Icon from '~/vue_shared/components/icon.vue';
|
||||
|
@ -311,7 +311,7 @@ export default {
|
|||
},
|
||||
onKeyup(event) {
|
||||
const { key } = event;
|
||||
if (key === ESC_KEY || key === ESC_KEY_IE11) {
|
||||
if (key === ESC_KEY) {
|
||||
this.clearExpandedPanel();
|
||||
}
|
||||
},
|
||||
|
|
|
@ -191,7 +191,7 @@ export default {
|
|||
name="eye-slash"
|
||||
:size="14"
|
||||
:title="s__('Notes|Private comments are accessible by internal staff only')"
|
||||
class="gl-ml-1 gl-text-gray-800 align-middle"
|
||||
class="gl-ml-1 gl-text-gray-700 align-middle"
|
||||
/>
|
||||
<slot name="extra-controls"></slot>
|
||||
<i
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import $ from 'jquery';
|
||||
import { parseBoolean, getCookie, setCookie, removeCookie } from '~/lib/utils/common_utils';
|
||||
import { __ } from '~/locale';
|
||||
import { __, sprintf } from '~/locale';
|
||||
import Tracking from '~/tracking';
|
||||
|
||||
const COOKIE_NAME = 'onboarding_issues_settings';
|
||||
|
@ -94,8 +94,12 @@ export const showLearnGitLabProjectPopover = () => {
|
|||
if (!el) return;
|
||||
|
||||
const options = {
|
||||
content: __(
|
||||
'Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board.',
|
||||
content: sprintf(
|
||||
__(
|
||||
'Go to %{strongStart}Issues%{strongEnd} > %{strongStart}Boards%{strongEnd} to access your personalized learning issue board.',
|
||||
),
|
||||
{ strongStart: '<strong>', strongEnd: '</strong>' },
|
||||
false,
|
||||
),
|
||||
};
|
||||
|
||||
|
@ -111,8 +115,12 @@ export const showLearnGitLabIssuesPopover = () => {
|
|||
if (!el) return;
|
||||
|
||||
const options = {
|
||||
content: __(
|
||||
'Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board.',
|
||||
content: sprintf(
|
||||
__(
|
||||
'Go to %{strongStart}Issues%{strongEnd} > %{strongStart}Boards%{strongEnd} to access your personalized learning issue board.',
|
||||
),
|
||||
{ strongStart: '<strong>', strongEnd: '</strong>' },
|
||||
false,
|
||||
),
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
<script>
|
||||
import { GlBanner } from '@gitlab/ui';
|
||||
import { s__ } from '~/locale';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GlBanner,
|
||||
},
|
||||
inject: {
|
||||
svgPath: {
|
||||
default: '',
|
||||
},
|
||||
preferencesBehaviorPath: {
|
||||
default: '',
|
||||
},
|
||||
calloutsPath: {
|
||||
default: '',
|
||||
},
|
||||
calloutsFeatureId: {
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
i18n: {
|
||||
title: s__('CustomizeHomepageBanner|Do you want to customize this page?'),
|
||||
body: s__(
|
||||
'CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects\' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under "Homepage content" in your preferences',
|
||||
),
|
||||
button_text: s__('CustomizeHomepageBanner|Go to preferences'),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
visible: true,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handleClose() {
|
||||
axios
|
||||
.post(this.calloutsPath, {
|
||||
feature_name: this.calloutsFeatureId,
|
||||
})
|
||||
.catch(e => {
|
||||
// eslint-disable-next-line @gitlab/require-i18n-strings, no-console
|
||||
console.error('Failed to dismiss banner.', e);
|
||||
});
|
||||
|
||||
this.visible = false;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<gl-banner
|
||||
v-if="visible"
|
||||
:title="$options.i18n.title"
|
||||
:button-text="$options.i18n.button_text"
|
||||
:button-link="preferencesBehaviorPath"
|
||||
:svg-path="svgPath"
|
||||
@close="handleClose"
|
||||
>
|
||||
<p>
|
||||
{{ $options.i18n.body }}
|
||||
</p>
|
||||
</gl-banner>
|
||||
</template>
|
|
@ -1,5 +1,8 @@
|
|||
import ProjectsList from '~/projects_list';
|
||||
import initCustomizeHomepageBanner from './init_customize_homepage_banner';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
new ProjectsList(); // eslint-disable-line no-new
|
||||
|
||||
initCustomizeHomepageBanner();
|
||||
});
|
|
@ -0,0 +1,16 @@
|
|||
import Vue from 'vue';
|
||||
import CustomizeHomepageBanner from './components/customize_homepage_banner.vue';
|
||||
|
||||
export default () => {
|
||||
const el = document.querySelector('.js-customize-homepage-banner');
|
||||
|
||||
if (!el) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return new Vue({
|
||||
el,
|
||||
provide: { ...el.dataset },
|
||||
render: createElement => createElement(CustomizeHomepageBanner),
|
||||
});
|
||||
};
|
|
@ -1,15 +1,16 @@
|
|||
<script>
|
||||
import { escape } from 'lodash';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import createFlash from '~/flash';
|
||||
import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
|
||||
import { s__, sprintf } from '~/locale';
|
||||
import { visitUrl } from '~/lib/utils/url_utility';
|
||||
import eventHub from '../event_hub';
|
||||
import { GlSprintf } from '@gitlab/ui';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GlModal: DeprecatedModal2,
|
||||
GlSprintf,
|
||||
},
|
||||
props: {
|
||||
url: {
|
||||
|
@ -45,20 +46,6 @@ export default {
|
|||
},
|
||||
);
|
||||
},
|
||||
title() {
|
||||
const label = `<span
|
||||
class="label color-label"
|
||||
style="background-color: ${this.labelColor}; color: ${this.labelTextColor};"
|
||||
>${escape(this.labelTitle)}</span>`;
|
||||
|
||||
return sprintf(
|
||||
s__('Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>'),
|
||||
{
|
||||
labelTitle: label,
|
||||
},
|
||||
false,
|
||||
);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onSubmit() {
|
||||
|
@ -90,7 +77,27 @@ export default {
|
|||
footer-primary-button-variant="warning"
|
||||
@submit="onSubmit"
|
||||
>
|
||||
<div slot="title" class="modal-title-with-label" v-html="title"></div>
|
||||
<div slot="title" class="modal-title-with-label">
|
||||
<gl-sprintf
|
||||
:message="
|
||||
s__(
|
||||
'Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}',
|
||||
)
|
||||
"
|
||||
>
|
||||
<template #labelTitle>
|
||||
<span
|
||||
class="label color-label"
|
||||
:style="`background-color: ${labelColor}; color: ${labelTextColor};`"
|
||||
>
|
||||
{{ labelTitle }}
|
||||
</span>
|
||||
</template>
|
||||
<template #span="{ content }"
|
||||
><span>{{ content }}</span></template
|
||||
>
|
||||
</gl-sprintf>
|
||||
</div>
|
||||
|
||||
{{ text }}
|
||||
</gl-modal>
|
||||
|
|
|
@ -87,16 +87,15 @@ export default class PrometheusMetrics {
|
|||
|
||||
if (totalMonitoredMetrics === 0) {
|
||||
const emptyCommonMetricsText = sprintf(
|
||||
s__(
|
||||
'PrometheusService|<p class="text-tertiary">No <a href="%{docsUrl}">common metrics</a> were found</p>',
|
||||
),
|
||||
s__('PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found'),
|
||||
{
|
||||
docsUrl: this.helpMetricsPath,
|
||||
docsUrlStart: `<a href="${this.helpMetricsPath}">`,
|
||||
docsUrlEnd: '</a>',
|
||||
},
|
||||
false,
|
||||
);
|
||||
this.$monitoredMetricsEmpty.empty();
|
||||
this.$monitoredMetricsEmpty.append(emptyCommonMetricsText);
|
||||
this.$monitoredMetricsEmpty.append(`<p class="text-tertiary">${emptyCommonMetricsText}</p>`);
|
||||
this.showMonitoringMetricsPanelState(PANEL_STATE.EMPTY);
|
||||
} else {
|
||||
const metricsCountText = sprintf(
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
<script>
|
||||
import editFormButtons from './edit_form_buttons.vue';
|
||||
import { __, sprintf } from '../../../locale';
|
||||
import { __ } from '../../../locale';
|
||||
import { GlSprintf } from '@gitlab/ui';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
editFormButtons,
|
||||
GlSprintf,
|
||||
},
|
||||
props: {
|
||||
confidential: {
|
||||
|
@ -22,25 +24,13 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
confidentialityOnWarning() {
|
||||
const accessLevel = __('at least Reporter access');
|
||||
|
||||
return sprintf(
|
||||
__(
|
||||
'You are going to turn on the confidentiality. This means that only team members with %{accessLevel} are able to see and leave comments on the %{issuableType}.',
|
||||
),
|
||||
{ issuableType: this.issuableType, accessLevel: `<strong>${accessLevel}</strong>` },
|
||||
false,
|
||||
return __(
|
||||
'You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}.',
|
||||
);
|
||||
},
|
||||
confidentialityOffWarning() {
|
||||
const accessLevel = __('everyone');
|
||||
|
||||
return sprintf(
|
||||
__(
|
||||
'You are going to turn off the confidentiality. This means %{accessLevel} will be able to see and leave a comment on this %{issuableType}.',
|
||||
),
|
||||
{ issuableType: this.issuableType, accessLevel: `<strong>${accessLevel}</strong>` },
|
||||
false,
|
||||
return __(
|
||||
'You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}.',
|
||||
);
|
||||
},
|
||||
},
|
||||
|
@ -51,8 +41,22 @@ export default {
|
|||
<div class="dropdown show">
|
||||
<div class="dropdown-menu sidebar-item-warning-message">
|
||||
<div>
|
||||
<p v-if="!confidential" v-html="confidentialityOnWarning"></p>
|
||||
<p v-else v-html="confidentialityOffWarning"></p>
|
||||
<p v-if="!confidential">
|
||||
<gl-sprintf :message="confidentialityOnWarning">
|
||||
<template #strong="{ content }">
|
||||
<strong>{{ content }}</strong>
|
||||
</template>
|
||||
<template #issuableType>{{ issuableType }}</template>
|
||||
</gl-sprintf>
|
||||
</p>
|
||||
<p v-else>
|
||||
<gl-sprintf :message="confidentialityOffWarning">
|
||||
<template #strong="{ content }">
|
||||
<strong>{{ content }}</strong>
|
||||
</template>
|
||||
<template #issuableType>{{ issuableType }}</template>
|
||||
</gl-sprintf>
|
||||
</p>
|
||||
<edit-form-buttons :full-path="fullPath" :confidential="confidential" />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
<script>
|
||||
import editFormButtons from './edit_form_buttons.vue';
|
||||
import { __, sprintf } from '../../../locale';
|
||||
import { GlSprintf } from '@gitlab/ui';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
editFormButtons,
|
||||
GlSprintf,
|
||||
},
|
||||
props: {
|
||||
isLocked: {
|
||||
|
@ -16,33 +17,41 @@ export default {
|
|||
type: String,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
lockWarning() {
|
||||
return sprintf(
|
||||
__(
|
||||
'Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment.',
|
||||
),
|
||||
{ issuableDisplayName: this.issuableDisplayName },
|
||||
);
|
||||
},
|
||||
unlockWarning() {
|
||||
return sprintf(
|
||||
__(
|
||||
'Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment.',
|
||||
),
|
||||
{ issuableDisplayName: this.issuableDisplayName },
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="dropdown show">
|
||||
<div class="dropdown-menu sidebar-item-warning-message" data-testid="warning-text">
|
||||
<p v-if="isLocked" class="text" v-html="unlockWarning"></p>
|
||||
<p v-if="isLocked" class="text">
|
||||
<gl-sprintf
|
||||
:message="
|
||||
__(
|
||||
'Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment.',
|
||||
)
|
||||
"
|
||||
>
|
||||
<template #issuableDisplayName>{{ issuableDisplayName }}</template>
|
||||
<template #strong="{ content }"
|
||||
><strong>{{ content }}</strong></template
|
||||
>
|
||||
</gl-sprintf>
|
||||
</p>
|
||||
|
||||
<p v-else class="text" v-html="lockWarning"></p>
|
||||
<p v-else class="text">
|
||||
<gl-sprintf
|
||||
:message="
|
||||
__(
|
||||
'Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment.',
|
||||
)
|
||||
"
|
||||
>
|
||||
<template #issuableDisplayName>{{ issuableDisplayName }}</template>
|
||||
<template #strong="{ content }"
|
||||
><strong>{{ content }}</strong></template
|
||||
>
|
||||
</gl-sprintf>
|
||||
</p>
|
||||
|
||||
<edit-form-buttons :is-locked="isLocked" :issuable-display-name="issuableDisplayName" />
|
||||
</div>
|
||||
|
|
|
@ -1,22 +1,37 @@
|
|||
<script>
|
||||
import tooltip from '../../vue_shared/directives/tooltip';
|
||||
import { __ } from '../../locale';
|
||||
import { GlSprintf } from '@gitlab/ui';
|
||||
|
||||
export default {
|
||||
i18n: {
|
||||
removesBranchText: __('%{strongStart}Deletes%{strongEnd} source branch'),
|
||||
tooltipTitle: __('A user with write access to the source branch selected this option'),
|
||||
},
|
||||
components: {
|
||||
GlSprintf,
|
||||
},
|
||||
directives: {
|
||||
tooltip,
|
||||
},
|
||||
created() {
|
||||
this.removesBranchText = __('<strong>Deletes</strong> source branch');
|
||||
this.tooltipTitle = __('A user with write access to the source branch selected this option');
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<p v-once class="mr-info-list mr-links gl-mb-0">
|
||||
<span class="status-text" v-html="removesBranchText"> </span>
|
||||
<i v-tooltip :title="tooltipTitle" :aria-label="tooltipTitle" class="fa fa-question-circle">
|
||||
<span class="status-text">
|
||||
<gl-sprintf :message="$options.i18n.removesBranchText">
|
||||
<template #strong="{ content }">
|
||||
<strong>{{ content }}</strong>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</span>
|
||||
<i
|
||||
v-tooltip
|
||||
:title="$options.i18n.tooltipTitle"
|
||||
:aria-label="$options.i18n.tooltipTitle"
|
||||
class="fa fa-question-circle"
|
||||
>
|
||||
</i>
|
||||
</p>
|
||||
</template>
|
||||
|
|
|
@ -125,7 +125,7 @@ $identicon-backgrounds: $identicon-red, $identicon-purple, $identicon-indigo, $i
|
|||
.identicon {
|
||||
text-align: center;
|
||||
vertical-align: top;
|
||||
color: $gray-800;
|
||||
color: $gray-700;
|
||||
background-color: $gray-darker;
|
||||
|
||||
// Sizes
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
}
|
||||
|
||||
button {
|
||||
@include gl-text-gray-800;
|
||||
@include gl-text-gray-700;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
.badge.badge-pill:not(.gl-badge) {
|
||||
font-weight: $gl-font-weight-normal;
|
||||
background-color: $badge-bg;
|
||||
color: $gray-800;
|
||||
color: $gray-700;
|
||||
vertical-align: baseline;
|
||||
|
||||
// Do not use this!
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
}
|
||||
|
||||
.broadcast-message-dismiss {
|
||||
color: $gray-800;
|
||||
color: $gray-700;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -297,7 +297,7 @@ body {
|
|||
$gray-200,
|
||||
$gray-300,
|
||||
$gray-500,
|
||||
$gray-800,
|
||||
$gray-700,
|
||||
$gray-900,
|
||||
$white
|
||||
);
|
||||
|
@ -306,7 +306,7 @@ body {
|
|||
&.ui-light {
|
||||
@include gitlab-theme(
|
||||
$gray-500,
|
||||
$gray-800,
|
||||
$gray-700,
|
||||
$gray-500,
|
||||
$gray-500,
|
||||
$gray-50,
|
||||
|
|
|
@ -285,7 +285,7 @@
|
|||
.select2-highlighted {
|
||||
.group-result {
|
||||
.group-path {
|
||||
color: $gray-800;
|
||||
color: $gray-700;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -170,7 +170,7 @@ $gray-400: #868686 !default;
|
|||
$gray-500: #666 !default;
|
||||
$gray-600: #5e5e5e !default;
|
||||
$gray-700: #525252 !default;
|
||||
$gray-800: #4f4f4f !default;
|
||||
$gray-800: #404040 !default;
|
||||
$gray-900: #303030 !default;
|
||||
$gray-950: #1f1f1f !default;
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
}
|
||||
|
||||
.badge.badge-pill {
|
||||
color: var(--ide-text-color, $gray-800);
|
||||
color: var(--ide-text-color, $gray-700);
|
||||
background-color: var(--ide-background, $badge-bg);
|
||||
}
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
text {
|
||||
font-weight: bold;
|
||||
font-size: 12px;
|
||||
fill: $gray-800;
|
||||
fill: $gray-700;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -336,11 +336,11 @@
|
|||
}
|
||||
|
||||
.label-action {
|
||||
color: $gray-800;
|
||||
color: $gray-700;
|
||||
cursor: pointer;
|
||||
|
||||
svg {
|
||||
fill: $gray-800;
|
||||
fill: $gray-700;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
|
|
|
@ -796,7 +796,7 @@
|
|||
&.ci-status-icon-disabled,
|
||||
&.ci-status-icon-not-found,
|
||||
&.ci-status-icon-manual {
|
||||
@include mini-pipeline-graph-color($white, $gray-500, $gray-800, $gray-900, $gray-950, $black);
|
||||
@include mini-pipeline-graph-color($white, $gray-500, $gray-700, $gray-900, $gray-950, $black);
|
||||
}
|
||||
|
||||
&.ci-status-icon-created,
|
||||
|
|
|
@ -13,6 +13,7 @@ class RootController < Dashboard::ProjectsController
|
|||
|
||||
before_action :redirect_unlogged_user, if: -> { current_user.nil? }
|
||||
before_action :redirect_logged_user, if: -> { current_user.present? }
|
||||
before_action :customize_homepage, only: :index, if: -> { current_user.present? }
|
||||
# We only need to load the projects when the user is logged in but did not
|
||||
# configure a dashboard. In which case we render projects. We can do that straight
|
||||
# from the #index action.
|
||||
|
@ -66,6 +67,10 @@ class RootController < Dashboard::ProjectsController
|
|||
|
||||
root_urls.exclude?(home_page_url)
|
||||
end
|
||||
|
||||
def customize_homepage
|
||||
@customize_homepage = experiment_enabled?(:customize_homepage)
|
||||
end
|
||||
end
|
||||
|
||||
RootController.prepend_if_ee('EE::RootController')
|
||||
|
|
|
@ -14,7 +14,8 @@ module Resolvers
|
|||
def resolve(**args)
|
||||
return unless environment
|
||||
|
||||
::PerformanceMonitoring::PrometheusDashboard.find_for(project: environment.project, user: context[:current_user], path: args[:path], options: { environment: environment })
|
||||
::PerformanceMonitoring::PrometheusDashboard
|
||||
.find_for(project: environment.project, user: context[:current_user], path: args[:path], options: { environment: environment })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -45,8 +45,9 @@ module Types
|
|||
description: 'Stages of the pipeline',
|
||||
extras: [:lookahead],
|
||||
resolver: Resolvers::Ci::PipelineStagesResolver
|
||||
|
||||
# TODO: Add triggering user as a type
|
||||
field :user, Types::UserType, null: true,
|
||||
description: 'Pipeline user',
|
||||
resolve: -> (pipeline, _args, _context) { Gitlab::Graphql::Loaders::BatchModelLoader.new(User, pipeline.user_id).find }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -16,6 +16,13 @@ module Types
|
|||
field :annotations, Types::Metrics::Dashboards::AnnotationType.connection_type, null: true,
|
||||
description: 'Annotations added to the dashboard',
|
||||
resolver: Resolvers::Metrics::Dashboards::AnnotationResolver
|
||||
|
||||
# In order to maintain backward compatibility we need to return NULL when there are no warnings
|
||||
# and dashboard validation returns an empty array when there are no issues.
|
||||
def schema_validation_warnings
|
||||
warnings = object.schema_validation_warnings
|
||||
warnings unless warnings.empty?
|
||||
end
|
||||
end
|
||||
# rubocop: enable Graphql/AuthorizeTypes
|
||||
end
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Types
|
||||
# rubocop: disable Graphql/AuthorizeTypes
|
||||
class UserStatusType < BaseObject
|
||||
graphql_name 'UserStatus'
|
||||
|
||||
markdown_field :message_html, null: true,
|
||||
description: 'HTML of the user status message'
|
||||
field :message, GraphQL::STRING_TYPE, null: true,
|
||||
description: 'User status message'
|
||||
field :emoji, GraphQL::STRING_TYPE, null: true,
|
||||
description: 'String representation of emoji'
|
||||
end
|
||||
end
|
|
@ -18,6 +18,8 @@ module Types
|
|||
description: 'Human-readable name of the user'
|
||||
field :state, Types::UserStateEnum, null: false,
|
||||
description: 'State of the user'
|
||||
field :email, GraphQL::STRING_TYPE, null: true,
|
||||
description: 'User email'
|
||||
field :avatar_url, GraphQL::STRING_TYPE, null: true,
|
||||
description: "URL of the user's avatar"
|
||||
field :web_url, GraphQL::STRING_TYPE, null: false,
|
||||
|
@ -30,6 +32,8 @@ module Types
|
|||
field :group_memberships, Types::GroupMemberType.connection_type, null: true,
|
||||
description: 'Group memberships of the user',
|
||||
method: :group_members
|
||||
field :status, Types::UserStatusType, null: true,
|
||||
description: 'User status'
|
||||
field :project_memberships, Types::ProjectMemberType.connection_type, null: true,
|
||||
description: 'Project memberships of the user',
|
||||
method: :project_members
|
||||
|
|
|
@ -7,6 +7,7 @@ module UserCalloutsHelper
|
|||
SUGGEST_POPOVER_DISMISSED = 'suggest_popover_dismissed'
|
||||
TABS_POSITION_HIGHLIGHT = 'tabs_position_highlight'
|
||||
WEBHOOKS_MOVED = 'webhooks_moved'
|
||||
CUSTOMIZE_HOMEPAGE = 'customize_homepage'
|
||||
|
||||
def show_admin_integrations_moved?
|
||||
!user_dismissed?(ADMIN_INTEGRATIONS_MOVED)
|
||||
|
@ -44,6 +45,10 @@ module UserCalloutsHelper
|
|||
!user_dismissed?(WEBHOOKS_MOVED)
|
||||
end
|
||||
|
||||
def show_customize_homepage_banner?(customize_homepage)
|
||||
customize_homepage && !user_dismissed?(CUSTOMIZE_HOMEPAGE)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def user_dismissed?(feature_name, ignore_dismissal_earlier_than = nil)
|
||||
|
|
|
@ -26,19 +26,10 @@ module BlobViewer
|
|||
|
||||
def parse_blob_data
|
||||
yaml = ::Gitlab::Config::Loader::Yaml.new(blob.data).load_raw!
|
||||
|
||||
::PerformanceMonitoring::PrometheusDashboard.from_json(yaml)
|
||||
nil
|
||||
Gitlab::Metrics::Dashboard::Validator
|
||||
.errors(yaml, dashboard_path: blob.path, project: project)
|
||||
rescue Gitlab::Config::Loader::FormatError => error
|
||||
wrap_yml_syntax_error(error)
|
||||
rescue ActiveModel::ValidationError => invalid
|
||||
invalid.model.errors
|
||||
end
|
||||
|
||||
def wrap_yml_syntax_error(error)
|
||||
::PerformanceMonitoring::PrometheusDashboard.new.errors.tap do |errors|
|
||||
errors.add(:'YAML syntax', error.message)
|
||||
end
|
||||
[error]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -23,6 +23,7 @@ class Discussion
|
|||
:resolved_by_id,
|
||||
:system_note_with_references_visible_for?,
|
||||
:resource_parent,
|
||||
:save,
|
||||
|
||||
to: :first_note
|
||||
|
||||
|
|
|
@ -17,12 +17,8 @@ class IndividualNoteDiscussion < Discussion
|
|||
noteable.supports_replying_to_individual_notes?
|
||||
end
|
||||
|
||||
def convert_to_discussion!(save: false)
|
||||
first_note.becomes!(Discussion.note_class).to_discussion.tap do
|
||||
# Save needs to be called on first_note instead of the transformed note
|
||||
# because of https://gitlab.com/gitlab-org/gitlab-foss/issues/57324
|
||||
first_note.save if save
|
||||
end
|
||||
def convert_to_discussion!
|
||||
first_note.becomes!(Discussion.note_class).to_discussion
|
||||
end
|
||||
|
||||
def reply_attributes
|
||||
|
|
|
@ -53,14 +53,18 @@ module PerformanceMonitoring
|
|||
# This method is planned to be refactored as a part of https://gitlab.com/gitlab-org/gitlab/-/issues/219398
|
||||
# implementation. For new existing logic was reused to faster deliver MVC
|
||||
def schema_validation_warnings
|
||||
self.class.from_json(reload_schema)
|
||||
nil
|
||||
rescue ActiveModel::ValidationError => exception
|
||||
exception.model.errors.map { |attr, error| "#{attr}: #{error}" }
|
||||
run_custom_validation.map(&:message)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def run_custom_validation
|
||||
Gitlab::Metrics::Dashboard::Validator
|
||||
.errors(reload_schema, dashboard_path: path, project: environment&.project)
|
||||
rescue Gitlab::Config::Loader::FormatError => error
|
||||
[error.message]
|
||||
end
|
||||
|
||||
# dashboard finder methods are somehow limited, #find includes checking if
|
||||
# user is authorised to view selected dashboard, but modifies schema, which in some cases may
|
||||
# cause false positives returned from validation, and #find_raw does not authorise users
|
||||
|
|
|
@ -220,6 +220,7 @@ class Repository
|
|||
prefix_regex.match?(ref)
|
||||
end
|
||||
end
|
||||
cache_method :has_ambiguous_refs?
|
||||
|
||||
def expand_ref(ref)
|
||||
if tag_exists?(ref)
|
||||
|
@ -311,12 +312,12 @@ class Repository
|
|||
end
|
||||
|
||||
def expire_tags_cache
|
||||
expire_method_caches(%i(tag_names tag_count))
|
||||
expire_method_caches(%i(tag_names tag_count has_ambiguous_refs?))
|
||||
@tags = nil
|
||||
end
|
||||
|
||||
def expire_branches_cache
|
||||
expire_method_caches(%i(branch_names merged_branch_names branch_count has_visible_content?))
|
||||
expire_method_caches(%i(branch_names merged_branch_names branch_count has_visible_content? has_ambiguous_refs?))
|
||||
@local_branches = nil
|
||||
@branch_exists_memo = nil
|
||||
end
|
||||
|
|
|
@ -19,7 +19,8 @@ module UserCalloutEnums
|
|||
webhooks_moved: 13,
|
||||
admin_integrations_moved: 15,
|
||||
personal_access_token_expiry: 21, # EE-only
|
||||
suggest_pipeline: 22
|
||||
suggest_pipeline: 22,
|
||||
customize_homepage: 23
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -54,7 +54,8 @@ module Notes
|
|||
|
||||
def when_saved(note)
|
||||
if note.part_of_discussion? && note.discussion.can_convert_to_discussion?
|
||||
note.discussion.convert_to_discussion!(save: true)
|
||||
note.discussion.convert_to_discussion!.save
|
||||
note.clear_memoization(:discussion)
|
||||
end
|
||||
|
||||
todo_service.new_note(note, current_user)
|
||||
|
|
|
@ -3,6 +3,14 @@
|
|||
= content_for :meta_tags do
|
||||
= auto_discovery_link_tag(:atom, dashboard_projects_url(rss_url_options), title: "All activity")
|
||||
|
||||
- if show_customize_homepage_banner?(@customize_homepage)
|
||||
= content_for :customize_homepage_banner do
|
||||
.d-none.d-md-block{ class: "gl-pt-6! gl-pb-2! #{(container_class unless @no_container)} #{@content_class}" }
|
||||
.js-customize-homepage-banner{ data: { svg_path: image_path('illustrations/monitoring/getting_started.svg'),
|
||||
preferences_behavior_path: profile_preferences_path(anchor: 'behavior'),
|
||||
callouts_path: user_callouts_path,
|
||||
callouts_feature_id: UserCalloutsHelper::CUSTOMIZE_HOMEPAGE } }
|
||||
|
||||
= render_dashboard_gold_trial(current_user)
|
||||
|
||||
- page_title _("Projects")
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
= render_account_recovery_regular_check
|
||||
= render_if_exists "layouts/header/ee_subscribable_banner"
|
||||
= render_if_exists "shared/namespace_storage_limit_alert"
|
||||
= yield :customize_homepage_banner
|
||||
- unless @hide_breadcrumbs
|
||||
= render "layouts/nav/breadcrumbs"
|
||||
.d-flex
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
= icon('warning fw')
|
||||
= _('Metrics Dashboard YAML definition is invalid:')
|
||||
%ul
|
||||
- viewer.errors.messages.each do |error|
|
||||
%li= error.join(': ')
|
||||
- viewer.errors.each do |error|
|
||||
%li= error
|
||||
|
||||
= link_to _('Learn more'), help_page_path('operations/metrics/dashboards/index.md')
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Fix missing resolve button when replying to notes in MRs
|
||||
merge_request: 39614
|
||||
author:
|
||||
type: fixed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Create IssueLink for Vulnerabilities that do not have them
|
||||
merge_request: 39098
|
||||
author:
|
||||
type: fixed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: 'GraphQL: Add user to pipeline + status and email to user + StatusType'
|
||||
merge_request: 39402
|
||||
author:
|
||||
type: added
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add default value for file_store to ci_pipeline_artifacts
|
||||
merge_request: 39349
|
||||
author:
|
||||
type: fixed
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: Change metrics dashboard schema validation messages into exhaustive list of
|
||||
all encountered errors.
|
||||
merge_request: 38925
|
||||
author:
|
||||
type: changed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Allow query/query_range keys in metrics dashboard to contain numbers
|
||||
merge_request: 39530
|
||||
author:
|
||||
type: changed
|
|
@ -0,0 +1,20 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddDefaultValueForFileStoreToPipelineArtifact < ActiveRecord::Migration[6.0]
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
DOWNTIME = false
|
||||
PIPELINE_ARTIFACT_LOCAL_FILE_STORE = 1
|
||||
|
||||
def up
|
||||
with_lock_retries do
|
||||
change_column_default :ci_pipeline_artifacts, :file_store, PIPELINE_ARTIFACT_LOCAL_FILE_STORE
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
with_lock_retries do
|
||||
change_column_default :ci_pipeline_artifacts, :file_store, nil
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CreateIndexVulnerabilitiesFeedbackIssueIdNotNull < ActiveRecord::Migration[6.0]
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
DOWNTIME = false
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
add_concurrent_index :vulnerability_feedback, :id, where: 'issue_id IS NOT NULL',
|
||||
name: "index_vulnerability_feedback_on_issue_id_not_null"
|
||||
end
|
||||
|
||||
def down
|
||||
remove_concurrent_index_by_name :vulnerability_feedback,
|
||||
:index_vulnerability_feedback_on_issue_id_not_null
|
||||
end
|
||||
end
|
|
@ -0,0 +1,49 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CreateMissingVulnerabilitiesIssueLinks < ActiveRecord::Migration[6.0]
|
||||
class VulnerabilitiesFeedback < ActiveRecord::Base
|
||||
include EachBatch
|
||||
self.table_name = 'vulnerability_feedback'
|
||||
end
|
||||
|
||||
class VulnerabilitiesIssueLink < ActiveRecord::Base
|
||||
self.table_name = 'vulnerability_issue_links'
|
||||
LINK_TYPE_CREATED = 2
|
||||
end
|
||||
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
DOWNTIME = false
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
# https://github.com/rails/rails/issues/35493
|
||||
VulnerabilitiesFeedback.where('issue_id IS NOT NULL').each_batch do |relation|
|
||||
timestamp = Time.now
|
||||
values = relation
|
||||
.joins("JOIN vulnerability_occurrences vo ON vo.project_id = vulnerability_feedback.project_id AND vo.report_type = vulnerability_feedback.category AND encode(vo.project_fingerprint, 'hex') = vulnerability_feedback.project_fingerprint")
|
||||
.pluck(:vulnerability_id, :issue_id)
|
||||
.map do |v_id, i_id|
|
||||
{
|
||||
vulnerability_id: v_id,
|
||||
issue_id: i_id,
|
||||
link_type: VulnerabilitiesIssueLink::LINK_TYPE_CREATED,
|
||||
created_at: timestamp,
|
||||
updated_at: timestamp
|
||||
}
|
||||
end
|
||||
|
||||
next if values.empty?
|
||||
|
||||
VulnerabilitiesIssueLink.insert_all(
|
||||
values,
|
||||
returning: false,
|
||||
unique_by: %i[vulnerability_id issue_id]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
end
|
||||
end
|
|
@ -0,0 +1 @@
|
|||
36d3db5618a56a0ea03272563fe254590d6af1f7d2610a1f01a5054b1cda1a7d
|
|
@ -0,0 +1 @@
|
|||
e8fc0809b5bd3248dc625602deeaaef16e2db6b33d8eaf51fdcc1c67dee49e17
|
|
@ -0,0 +1 @@
|
|||
c45bbd5aa9143e039d41448f1cb4a2e8e0a7b2c165b50e89b1b829bbbe81f137
|
|
@ -10061,7 +10061,7 @@ CREATE TABLE public.ci_pipeline_artifacts (
|
|||
pipeline_id bigint NOT NULL,
|
||||
project_id bigint NOT NULL,
|
||||
size integer NOT NULL,
|
||||
file_store smallint NOT NULL,
|
||||
file_store smallint DEFAULT 1 NOT NULL,
|
||||
file_type smallint NOT NULL,
|
||||
file_format smallint NOT NULL,
|
||||
file text,
|
||||
|
@ -20971,6 +20971,8 @@ CREATE INDEX index_vulnerability_feedback_on_comment_author_id ON public.vulnera
|
|||
|
||||
CREATE INDEX index_vulnerability_feedback_on_issue_id ON public.vulnerability_feedback USING btree (issue_id);
|
||||
|
||||
CREATE INDEX index_vulnerability_feedback_on_issue_id_not_null ON public.vulnerability_feedback USING btree (id) WHERE (issue_id IS NOT NULL);
|
||||
|
||||
CREATE INDEX index_vulnerability_feedback_on_merge_request_id ON public.vulnerability_feedback USING btree (merge_request_id);
|
||||
|
||||
CREATE INDEX index_vulnerability_feedback_on_pipeline_id ON public.vulnerability_feedback USING btree (pipeline_id);
|
||||
|
|
|
@ -10422,6 +10422,11 @@ type Pipeline {
|
|||
"""
|
||||
updatedAt: Time!
|
||||
|
||||
"""
|
||||
Pipeline user
|
||||
"""
|
||||
user: User
|
||||
|
||||
"""
|
||||
Permissions for the current user on the resource
|
||||
"""
|
||||
|
@ -16462,6 +16467,11 @@ type User {
|
|||
"""
|
||||
avatarUrl: String
|
||||
|
||||
"""
|
||||
User email
|
||||
"""
|
||||
email: String
|
||||
|
||||
"""
|
||||
Group memberships of the user
|
||||
"""
|
||||
|
@ -16567,6 +16577,11 @@ type User {
|
|||
"""
|
||||
state: UserState!
|
||||
|
||||
"""
|
||||
User status
|
||||
"""
|
||||
status: UserStatus
|
||||
|
||||
"""
|
||||
Todos of the user
|
||||
"""
|
||||
|
@ -16705,6 +16720,23 @@ enum UserState {
|
|||
deactivated
|
||||
}
|
||||
|
||||
type UserStatus {
|
||||
"""
|
||||
String representation of emoji
|
||||
"""
|
||||
emoji: String
|
||||
|
||||
"""
|
||||
User status message
|
||||
"""
|
||||
message: String
|
||||
|
||||
"""
|
||||
HTML of the user status message
|
||||
"""
|
||||
messageHtml: String
|
||||
}
|
||||
|
||||
enum VisibilityLevelsEnum {
|
||||
internal
|
||||
private
|
||||
|
|
|
@ -31145,6 +31145,20 @@
|
|||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "user",
|
||||
"description": "Pipeline user",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "OBJECT",
|
||||
"name": "User",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "userPermissions",
|
||||
"description": "Permissions for the current user on the resource",
|
||||
|
@ -48275,6 +48289,20 @@
|
|||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "email",
|
||||
"description": "User email",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "groupMemberships",
|
||||
"description": "Group memberships of the user",
|
||||
|
@ -48526,6 +48554,20 @@
|
|||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "status",
|
||||
"description": "User status",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "OBJECT",
|
||||
"name": "UserStatus",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "todos",
|
||||
"description": "Todos of the user",
|
||||
|
@ -48943,6 +48985,61 @@
|
|||
],
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "UserStatus",
|
||||
"description": null,
|
||||
"fields": [
|
||||
{
|
||||
"name": "emoji",
|
||||
"description": "String representation of emoji",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "message",
|
||||
"description": "User status message",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "messageHtml",
|
||||
"description": "HTML of the user status message",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"inputFields": null,
|
||||
"interfaces": [
|
||||
|
||||
],
|
||||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "ENUM",
|
||||
"name": "VisibilityLevelsEnum",
|
||||
|
|
|
@ -1604,6 +1604,7 @@ Information about pagination in a connection.
|
|||
| `startedAt` | Time | Timestamp when the pipeline was started |
|
||||
| `status` | PipelineStatusEnum! | Status of the pipeline (CREATED, WAITING_FOR_RESOURCE, PREPARING, PENDING, RUNNING, FAILED, SUCCESS, CANCELED, SKIPPED, MANUAL, SCHEDULED) |
|
||||
| `updatedAt` | Time! | Timestamp of the pipeline's last activity |
|
||||
| `user` | User | Pipeline user |
|
||||
| `userPermissions` | PipelinePermissions! | Permissions for the current user on the resource |
|
||||
|
||||
## PipelinePermissions
|
||||
|
@ -2434,9 +2435,11 @@ Autogenerated return type of UpdateSnippet
|
|||
| Name | Type | Description |
|
||||
| --- | ---- | ---------- |
|
||||
| `avatarUrl` | String | URL of the user's avatar |
|
||||
| `email` | String | User email |
|
||||
| `id` | ID! | ID of the user |
|
||||
| `name` | String! | Human-readable name of the user |
|
||||
| `state` | UserState! | State of the user |
|
||||
| `status` | UserStatus | User status |
|
||||
| `userPermissions` | UserPermissions! | Permissions for the current user on the resource |
|
||||
| `username` | String! | Username of the user. Unique within this instance of GitLab |
|
||||
| `webPath` | String! | Web path of the user |
|
||||
|
@ -2448,6 +2451,14 @@ Autogenerated return type of UpdateSnippet
|
|||
| --- | ---- | ---------- |
|
||||
| `createSnippet` | Boolean! | Indicates the user can perform `create_snippet` on this resource |
|
||||
|
||||
## UserStatus
|
||||
|
||||
| Name | Type | Description |
|
||||
| --- | ---- | ---------- |
|
||||
| `emoji` | String | String representation of emoji |
|
||||
| `message` | String | User status message |
|
||||
| `messageHtml` | String | HTML of the user status message |
|
||||
|
||||
## VulnerabilitiesCountByDay
|
||||
|
||||
Represents the count of vulnerabilities by severity on a particular day
|
||||
|
|
|
@ -131,7 +131,7 @@ There are four types of counters which are all found in `usage_data.rb`:
|
|||
- **Ordinary Batch Counters:** Simple count of a given ActiveRecord_Relation
|
||||
- **Distinct Batch Counters:** Distinct count of a given ActiveRecord_Relation on given column
|
||||
- **Alternative Counters:** Used for settings and configurations
|
||||
- **Redis Counters:** Used for in-memory counts. This method is being deprecated due to data inaccuracies and will be replaced with a persistent method.
|
||||
- **Redis Counters:** Used for in-memory counts.
|
||||
|
||||
NOTE: **Note:**
|
||||
Only use the provided counter methods. Each counter method contains a built in fail safe to isolate each counter to avoid breaking the entire Usage Ping.
|
||||
|
@ -256,8 +256,6 @@ redis_usage_data do
|
|||
)
|
||||
```
|
||||
|
||||
Note that Redis counters are in the [process of being deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/216330) and you should instead try to use Snowplow events instead. We're in the process of building [self-managed event tracking](https://gitlab.com/gitlab-org/telemetry/-/issues/373) and once this is available, we will convert all Redis counters into Snowplow events.
|
||||
|
||||
### Alternative Counters
|
||||
|
||||
Handles `StandardError` and fallbacks into -1 this way not all measures fail if we encounter one exception.
|
||||
|
|
|
@ -0,0 +1,194 @@
|
|||
---
|
||||
stage: Monitor
|
||||
group: Health
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||
---
|
||||
|
||||
# Alert details page
|
||||
|
||||
Navigate to the Alert details view by visiting the
|
||||
[Alert list](alerts.md) and selecting an alert from the
|
||||
list. You need least Developer [permissions](../../user/permissions.md) to access
|
||||
alerts.
|
||||
|
||||
Alerts provide **Overview** and **Alert details** tabs to give you the right
|
||||
amount of information you need.
|
||||
|
||||
## Alert overview tab
|
||||
|
||||
The **Overview** tab provides basic information about the alert:
|
||||
|
||||
![Alert Detail Overview](img/alert_detail_overview_v13_1.png)
|
||||
|
||||
## Alert details tab
|
||||
|
||||
![Alert Full Details](img/alert_detail_full_v13_1.png)
|
||||
|
||||
### Update an Alert's status
|
||||
|
||||
The Alert detail view enables you to update the Alert Status.
|
||||
See [Create and manage alerts in GitLab](alerts.md) for more details.
|
||||
|
||||
### Create an Issue from an Alert
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217745) in GitLab 13.1.
|
||||
|
||||
The Alert detail view enables you to create an issue with a
|
||||
description automatically populated from an alert. To create the issue,
|
||||
click the **Create Issue** button. You can then view the issue from the
|
||||
alert by clicking the **View Issue** button.
|
||||
|
||||
Closing a GitLab issue associated with an alert changes the alert's status to Resolved.
|
||||
See [Create and manage alerts in GitLab](alerts.md) for more details about alert statuses.
|
||||
|
||||
### Update an Alert's assignee
|
||||
|
||||
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3066) in GitLab 13.1.
|
||||
|
||||
The Alert detail view allows users to update the Alert assignee.
|
||||
|
||||
In large teams, where there is shared ownership of an alert, it can be difficult
|
||||
to track who is investigating and working on it. The Alert detail view
|
||||
enables you to update the Alert assignee:
|
||||
|
||||
NOTE: **Note:**
|
||||
GitLab currently only supports a single assignee per alert.
|
||||
|
||||
1. To display the list of current alerts, click
|
||||
**{cloud-gear}** **Operations > Alerts**:
|
||||
|
||||
![Alert List View Assignee(s)](img/alert_list_assignees_v13_1.png)
|
||||
|
||||
1. Select your desired alert to display its **Alert Details View**:
|
||||
|
||||
![Alert Details View Assignee(s)](img/alert_details_assignees_v13_1.png)
|
||||
|
||||
1. If the right sidebar is not expanded, click
|
||||
**{angle-double-right}** **Expand sidebar** to expand it.
|
||||
1. In the right sidebar, locate the **Assignee** and click **Edit**. From the
|
||||
dropdown menu, select each user you want to assign to the alert. GitLab creates
|
||||
a [To-Do list item](../../user/todos.md) for each user.
|
||||
|
||||
![Alert Details View Assignee(s)](img/alert_todo_assignees_v13_1.png)
|
||||
|
||||
To remove an assignee, click **Edit** next to the **Assignee** dropdown menu and
|
||||
deselect the user from the list of assignees, or click **Unassigned**.
|
||||
|
||||
### Alert system notes
|
||||
|
||||
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3066) in GitLab 13.1.
|
||||
|
||||
When you take action on an alert, this is logged as a system note,
|
||||
which is visible in the Alert Details view. This gives you a linear
|
||||
timeline of the alert's investigation and assignment history.
|
||||
|
||||
The following actions will result in a system note:
|
||||
|
||||
- [Updating the status of an alert](#update-an-alerts-status)
|
||||
- [Creating an issue based on an alert](#create-an-issue-from-an-alert)
|
||||
- [Assignment of an alert to a user](#update-an-alerts-assignee)
|
||||
|
||||
![Alert Details View System Notes](img/alert_detail_system_notes_v13_1.png)
|
||||
|
||||
### Create a To-Do from an Alert
|
||||
|
||||
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3066) in GitLab 13.1.
|
||||
|
||||
You can manually create [To-Do list items](../../user/todos.md) for yourself from the
|
||||
Alert details screen, and view them later on your **To-Do List**. To add a To-Do:
|
||||
|
||||
1. To display the list of current alerts, click
|
||||
**{cloud-gear}** **Operations > Alerts**.
|
||||
1. Select your desired alert to display its **Alert Management Details View**.
|
||||
1. Click the **Add a To-Do** button in the right sidebar:
|
||||
|
||||
![Alert Details Add A To Do](img/alert_detail_add_todo_v13_1.png)
|
||||
|
||||
Click the **To-Do** **{todo-done}** in the navigation bar to view your current To-Do list.
|
||||
|
||||
![Alert Details Added to Do](img/alert_detail_added_todo_v13_1.png)
|
||||
|
||||
### View an Alert's metrics data
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217768) in GitLab 13.2.
|
||||
|
||||
To view the metrics for an alert:
|
||||
|
||||
1. Sign in as a user with Developer or higher [permissions](../../user/permissions.md).
|
||||
1. Navigate to **{cloud-gear}** **Operations > Alerts**.
|
||||
1. Click the alert you want to view.
|
||||
1. Below the title of the alert, click the **Metrics** tab.
|
||||
|
||||
![Alert Metrics View](img/alert_detail_metrics_v13_2.png)
|
||||
|
||||
For GitLab-managed Prometheus instances, metrics data is automatically available
|
||||
for the alert, making it easy to see surrounding behavior. See
|
||||
[Managed Prometheus instances](../metrics/alerts.md#managed-prometheus-instances)
|
||||
for information on setting up alerts.
|
||||
|
||||
For externally-managed Prometheus instances, you can configure your alerting rules to
|
||||
display a chart in the alert. See
|
||||
[Embedding metrics based on alerts in incident issues](../metrics/embed.md#embedding-metrics-based-on-alerts-in-incident-issues)
|
||||
for information on how to appropriately configure your alerting rules. See
|
||||
[External Prometheus instances](../metrics/alerts.md#external-prometheus-instances)
|
||||
for information on setting up alerts for your self-managed Prometheus instance.
|
||||
|
||||
## Use cases for assigning alerts
|
||||
|
||||
Consider a team formed by different sections of monitoring, collaborating on a
|
||||
single application. After an alert surfaces, it's extremely important to
|
||||
route the alert to the team members who can address and resolve the alert.
|
||||
|
||||
Assigning Alerts eases collaboration and delegation. All
|
||||
assignees are shown in your team's work-flows, and all assignees receive
|
||||
notifications, simplifying communication and ownership of the alert.
|
||||
|
||||
After completing their portion of investigating or fixing the alert, users can
|
||||
unassign their account from the alert when their role is complete.
|
||||
The alert status can be updated on the [Alert list](alerts.md) to
|
||||
reflect if the alert has been resolved.
|
||||
|
||||
## View an Alert's logs
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217768) in GitLab 13.3.
|
||||
|
||||
To view the logs for an alert:
|
||||
|
||||
1. Sign in as a user with Developer or higher [permissions](../../user/permissions.md).
|
||||
1. Navigate to **{cloud-gear}** **Operations > Alerts**.
|
||||
1. Click the alert you want to view.
|
||||
1. Below the title of the alert, click the **Metrics** tab.
|
||||
1. Click the [menu](../metrics/dashboards/index.md#chart-context-menu) of the metric chart to view options.
|
||||
1. Click **View logs**.
|
||||
|
||||
Read [View logs from metrics panel](#view-logs-from-metrics-panel) for additional information.
|
||||
|
||||
## Embed metrics in incidents and issues
|
||||
|
||||
You can embed metrics anywhere [GitLab Markdown](../../user/markdown.md) is used, such as descriptions,
|
||||
comments on issues, and merge requests. Embedding metrics helps you share them
|
||||
when discussing incidents or performance issues. You can output the dashboard directly
|
||||
into any issue, merge request, epic, or any other Markdown text field in GitLab
|
||||
by [copying and pasting the link to the metrics dashboard](../metrics/embed.md#embedding-gitlab-managed-kubernetes-metrics).
|
||||
|
||||
You can embed both
|
||||
[GitLab-hosted metrics](../metrics/embed.md) and
|
||||
[Grafana metrics](../metrics/embed_grafana.md)
|
||||
in incidents and issue templates.
|
||||
|
||||
### Context menu
|
||||
|
||||
You can view more details about an embedded metrics panel from the context menu.
|
||||
To access the context menu, click the **{ellipsis_v}** **More actions** dropdown box
|
||||
above the upper right corner of the panel. For a list of options, see
|
||||
[Chart context menu](../metrics/dashboards/index.md#chart-context-menu).
|
||||
|
||||
#### View logs from metrics panel
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/201846) in GitLab Ultimate 12.8.
|
||||
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25455) to [GitLab Core](https://about.gitlab.com/pricing/) 12.9.
|
||||
|
||||
Viewing logs from a metrics panel can be useful if you're triaging an application
|
||||
incident and need to [explore logs](../metrics/dashboards/index.md#chart-context-menu)
|
||||
from across your application. These logs help you understand what is affecting
|
||||
your application's performance and resolve any problems.
|
|
@ -0,0 +1,118 @@
|
|||
---
|
||||
stage: Monitor
|
||||
group: Health
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||
---
|
||||
|
||||
# Create and manage alerts in GitLab
|
||||
|
||||
Users with at least Developer [permissions](../../user/permissions.md) can access
|
||||
the Alert Management list at **{cloud-gear}** **Operations > Alerts** in your
|
||||
project's sidebar. The Alert Management list displays alerts sorted by start time,
|
||||
but you can change the sort order by clicking the headers in the Alert Management list.
|
||||
([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217745) in GitLab 13.1.)
|
||||
|
||||
The alert list displays the following information:
|
||||
|
||||
![Alert List](../../user/project/operations/img/alert_list_v13_1.png)
|
||||
|
||||
- **Search** - The alert list supports a simple free text search on the title,
|
||||
description, monitoring tool, and service fields.
|
||||
([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213884) in GitLab 13.1.)
|
||||
- **Severity** - The current importance of a alert and how much attention it should
|
||||
receive. For a listing of all statuses, read [Alert Management severity](#alert-severity).
|
||||
- **Start time** - How long ago the alert fired. This field uses the standard
|
||||
GitLab pattern of `X time ago`, but is supported by a granular date/time tooltip
|
||||
depending on the user's locale.
|
||||
- **Alert description** - The description of the alert, which attempts to capture the most meaningful data.
|
||||
- **Event count** - The number of times that an alert has fired.
|
||||
- **Issue** - A link to the incident issue that has been created for the alert.
|
||||
- **Status** - The current status of the alert:
|
||||
- **Triggered**: No one has begun investigation.
|
||||
- **Acknowledged**: Someone is actively investigating the problem.
|
||||
- **Resolved**: No further work is required.
|
||||
|
||||
## Enable Alerts
|
||||
|
||||
NOTE: **Note:**
|
||||
You need at least Maintainer [permissions](../../user/permissions.md) to enable
|
||||
the Alerts feature.
|
||||
|
||||
There are several ways to accept alerts into your GitLab project.
|
||||
Enabling any of these methods enables the Alert list. After configuring
|
||||
alerts, visit **{cloud-gear}** **Operations > Alerts** in your project's sidebar
|
||||
to view the list of alerts.
|
||||
|
||||
### Enable GitLab-managed Prometheus alerts
|
||||
|
||||
You can install the GitLab-managed Prometheus application on your Kubernetes
|
||||
cluster. For more information, read
|
||||
[Managed Prometheus on Kubernetes](../../user/project/integrations/prometheus.md#managed-prometheus-on-kubernetes).
|
||||
When GitLab-managed Prometheus is installed, the [Alerts list](alerts.md)
|
||||
is also enabled.
|
||||
|
||||
To populate the alerts with data, read
|
||||
[GitLab-Managed Prometheus instances](../metrics/alerts.md#managed-prometheus-instances).
|
||||
|
||||
### Enable external Prometheus alerts
|
||||
|
||||
You can configure an externally-managed Prometheus instance to send alerts
|
||||
to GitLab. To set up this configuration, read the [configuring Prometheus](../metrics/alerts.md#external-prometheus-instances) documentation. Activating the external Prometheus
|
||||
configuration also enables the [Alerts list](alerts.md).
|
||||
|
||||
To populate the alerts with data, read
|
||||
[External Prometheus instances](../metrics/alerts.md#external-prometheus-instances).
|
||||
|
||||
### Enable a Generic Alerts endpoint
|
||||
|
||||
GitLab provides the Generic Alerts endpoint so you can accept alerts from a third-party
|
||||
alerts service. Read the
|
||||
[instructions for toggling generic alerts](../../user/project/integrations/generic_alerts.md#setting-up-generic-alerts)
|
||||
to add this option. After configuring the endpoint, the
|
||||
[Alerts list](alerts.md) is enabled.
|
||||
|
||||
To populate the alerts with data, read [Customizing the payload](../../user/project/integrations/generic_alerts.md#customizing-the-payload) for requests to the alerts endpoint.
|
||||
|
||||
### Opsgenie integration **(PREMIUM)**
|
||||
|
||||
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3066) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2.
|
||||
|
||||
A new way of monitoring Alerts via a GitLab integration is with
|
||||
[Opsgenie](https://www.atlassian.com/software/opsgenie).
|
||||
|
||||
NOTE: **Note:**
|
||||
If you enable the Opsgenie integration, you can't have other GitLab alert services,
|
||||
such as [Generic Alerts](../../user/project/integrations/generic_alerts.md) or
|
||||
Prometheus alerts, active at the same time.
|
||||
|
||||
To enable Opsgenie integration:
|
||||
|
||||
1. Sign in as a user with Maintainer or Owner [permissions](../../user/permissions.md).
|
||||
1. Navigate to **{cloud-gear}** **Operations > Alerts**.
|
||||
1. In the **Integrations** select box, select Opsgenie.
|
||||
1. Click the **Active** toggle.
|
||||
1. In the **API URL**, enter the base URL for your Opsgenie integration, such
|
||||
as `https://app.opsgenie.com/alert/list`.
|
||||
1. Click **Save changes**.
|
||||
|
||||
After enabling the integration, navigate to the Alerts list page at
|
||||
**{cloud-gear}** **Operations > Alerts**, and click **View alerts in Opsgenie**.
|
||||
|
||||
## Alert severity
|
||||
|
||||
Each level of alert contains a uniquely shaped and color-coded icon to help
|
||||
you identify the severity of a particular alert. These severity icons help you
|
||||
immediately identify which alerts you should prioritize investigating:
|
||||
|
||||
![Alert Management Severity System](img/alert_management_severity_v13_0.png)
|
||||
|
||||
Alerts contain one of the following icons:
|
||||
|
||||
| Severity | Icon | Color (hexadecimal) |
|
||||
|---|---|---|
|
||||
| Critical | **{severity-critical}** | `#8b2615` |
|
||||
| High | **{severity-high}** | `#c0341d` |
|
||||
| Medium | **{severity-medium}** | `#fca429` |
|
||||
| Low | **{severity-low}** | `#fdbc60` |
|
||||
| Info | **{severity-info}** | `#418cd8` |
|
||||
| Unknown | **{severity-unknown}** | `#bababa` |
|
|
@ -0,0 +1,103 @@
|
|||
---
|
||||
stage: Monitor
|
||||
group: Health
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||
---
|
||||
|
||||
# Create and manage incidents in GitLab
|
||||
|
||||
While no configuration is required to use the [manual features](#create-an-incident-manually)
|
||||
of incident management, some simple [configuration](#configure-incidents) is needed to automate incident creation.
|
||||
|
||||
For users with at least Developer [permissions](../../user/permissions.md), the
|
||||
Incident Management list is available at **Operations > Incidents**
|
||||
in your project's sidebar. The list contains the following metrics:
|
||||
|
||||
![Incident List](img/incident_list_sort_v13_3.png)
|
||||
|
||||
- **Status** - To filter incidents by their status, click **Open**, **Closed**,
|
||||
or **All** above the incident list.
|
||||
- **Search** - The Incident list supports a simple free text search, which filters
|
||||
on the **Title** and **Incident** fields.
|
||||
- **Incident** - The description of the incident, which attempts to capture the
|
||||
most meaningful data.
|
||||
- **Date created** - How long ago the incident was created. This field uses the
|
||||
standard GitLab pattern of `X time ago`, but is supported by a granular date/time
|
||||
tooltip depending on the user's locale.
|
||||
- **Assignees** - The user assigned to the incident.
|
||||
- **Published** - Displays a green check mark (**{check-circle}**) if the incident is published
|
||||
to a [Status Page](status_page.md).. **(ULTIMATE)**
|
||||
|
||||
The Incident list displays incidents sorted by incident created date.
|
||||
([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229534) to GitLab core in 13.3).)
|
||||
To see if a column is sortable, point your mouse at the header. Sortable columns
|
||||
display an arrow next to the column name.
|
||||
|
||||
NOTE: **Note:**
|
||||
Incidents share the [Issues API](../../user/project/issues/index.md).
|
||||
|
||||
## Configure incidents
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/4925) in GitLab Ultimate 11.11.
|
||||
|
||||
With Maintainer or higher [permissions](../../user/permissions.md), you can enable
|
||||
or disable Incident Management features in the GitLab user interface
|
||||
to create issues when alerts are triggered:
|
||||
|
||||
1. Navigate to **Settings > Operations > Incidents** and expand
|
||||
**Incidents**:
|
||||
|
||||
![Incident Management Settings](img/incident_management_settings_v13_3.png)
|
||||
|
||||
1. For GitLab versions 11.11 and greater, you can select the **Create an issue**
|
||||
checkbox to create an issue based on your own
|
||||
[issue templates](../../user/project/description_templates.md#creating-issue-templates).
|
||||
For more information, see
|
||||
[Trigger actions from alerts](../metrics/alerts.md#trigger-actions-from-alerts-ultimate) **(ULTIMATE)**.
|
||||
1. To create issues from alerts, select the template in the **Issue Template**
|
||||
select box.
|
||||
1. To send [separate email notifications](index.md#notify-developers-of-alerts) to users
|
||||
with [Developer permissions](../../user/permissions.md), select
|
||||
**Send a separate email notification to Developers**.
|
||||
1. Click **Save changes**.
|
||||
|
||||
Appropriately configured alerts include an
|
||||
[embedded chart](../metrics/embed.md#embedding-metrics-based-on-alerts-in-incident-issues)
|
||||
for the query corresponding to the alert. You can also configure GitLab to
|
||||
[close issues](../metrics/alerts.md#trigger-actions-from-alerts-ultimate)
|
||||
when you receive notification that the alert is resolved.
|
||||
|
||||
## Create an incident manually
|
||||
|
||||
> [Moved](https://gitlab.com/gitlab-org/monitor/health/-/issues/24) to GitLab core in 13.3.
|
||||
|
||||
For users with at least Developer [permissions](../../user/permissions.md), to create a Incident you can take any of the following actions:
|
||||
|
||||
- Navigate to **Operations > Incidents** and click **Create Incident**.
|
||||
- Create a new issue using the `incident` template available when creating it.
|
||||
- Create a new issue and assign the `incident` label to it.
|
||||
|
||||
![Incident List Create](img/incident_list_create_v13_3.png)
|
||||
|
||||
## Configure PagerDuty integration
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/119018) in GitLab 13.3.
|
||||
|
||||
You can set up a webhook with PagerDuty to automatically create a GitLab issue
|
||||
for each PagerDuty incident. This configuration requires you to make changes
|
||||
in both PagerDuty and GitLab:
|
||||
|
||||
1. Sign in as a user with Maintainer [permissions](../../user/permissions.md).
|
||||
1. Navigate to **Settings > Operations > Incidents** and expand **Incidents**.
|
||||
1. Select the **PagerDuty integration** tab:
|
||||
|
||||
![PagerDuty incidents integration](img/pagerduty_incidents_integration_v13_3.png)
|
||||
|
||||
1. Activate the integration, and save the changes in GitLab.
|
||||
1. Copy the value of **Webhook URL** for use in a later step.
|
||||
1. Follow the steps described in the
|
||||
[PagerDuty documentation](https://support.pagerduty.com/docs/webhooks)
|
||||
to add the webhook URL to a PagerDuty webhook integration.
|
||||
|
||||
To confirm the integration is successful, trigger a test incident from PagerDuty to
|
||||
confirm that a GitLab issue is created from the incident.
|
|
@ -14,324 +14,9 @@ being developed, efficiency and awareness can be increased.
|
|||
|
||||
GitLab offers solutions for handling incidents in your applications and services,
|
||||
such as [setting up Prometheus alerts](#configure-prometheus-alerts),
|
||||
[displaying metrics](#embed-metrics-in-incidents-and-issues), and sending notifications.
|
||||
While no configuration is required to use the [manual features](#create-an-incident-manually)
|
||||
of incident management, some simple [configuration](#configure-incidents) is needed to automate incident creation.
|
||||
[displaying metrics](alertdetails.md#embed-metrics-in-incidents-and-issues), and sending notifications.
|
||||
|
||||
For users with at least Developer [permissions](../../user/permissions.md), the
|
||||
Incident Management list is available at **Operations > Incidents**
|
||||
in your project's sidebar. The list contains the following metrics:
|
||||
|
||||
![Incident Management List](img/incident_list_sort_v13_3.png)
|
||||
|
||||
- **Incident** - The description of the incident, which attempts to capture the
|
||||
most meaningful data.
|
||||
- **Date created** - How long ago the incident was created. This field uses the
|
||||
standard GitLab pattern of `X time ago`, but is supported by a granular date/time
|
||||
tooltip depending on the user's locale.
|
||||
- **Assignees** - The user assigned to the incident.
|
||||
- **Published** - Whether or not an incident is published to the
|
||||
[Status Page](./status_page.md). **(ULTIMATE)**
|
||||
|
||||
The Incident Management list displays incidents sorted by incident created date.
|
||||
([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229534) to GitLab core in 13.3).)
|
||||
To see if a column is sortable, point your mouse at the header. Sortable columns
|
||||
display an arrow next to the column name.
|
||||
|
||||
The Incident list supports a simple free text search, which filters on the
|
||||
**Title** and **Incident** fields.
|
||||
|
||||
To filter incidents by their status, click **Open**, **Closed**, or **All**
|
||||
above the incident list.
|
||||
|
||||
NOTE: **Note:**
|
||||
Incidents share the [Issues API](../../user/project/issues/index.md).
|
||||
|
||||
## Enable Alert Management
|
||||
|
||||
NOTE: **Note:**
|
||||
You will need at least Maintainer [permissions](../../user/permissions.md) to enable the Alert Management feature.
|
||||
|
||||
There are several ways to accept alerts into your GitLab project, as outlined below.
|
||||
Enabling any of these methods will allow the Alerts list to display. After configuring
|
||||
alerts, visit **{cloud-gear}** **Operations > Alerts** in your project's sidebar
|
||||
to [view the list](#alert-management-list) of alerts.
|
||||
|
||||
### Opsgenie integration **(PREMIUM)**
|
||||
|
||||
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3066) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2.
|
||||
|
||||
A new way of monitoring Alerts via a GitLab integration is with
|
||||
[Opsgenie](https://www.atlassian.com/software/opsgenie).
|
||||
|
||||
NOTE: **Note:**
|
||||
If you enable the Opsgenie integration, you cannot have other GitLab alert services,
|
||||
such as [Generic Alerts](../../user/project/integrations/generic_alerts.md) or
|
||||
Prometheus alerts, active at the same time.
|
||||
|
||||
To enable Opsgenie integration:
|
||||
|
||||
1. Sign in as a user with Maintainer or Owner [permissions](../../user/permissions.md).
|
||||
1. Navigate to **{cloud-gear}** **Operations > Alerts**.
|
||||
1. In the **Integrations** select box, select Opsgenie.
|
||||
1. Click the **Active** toggle.
|
||||
1. In the **API URL**, enter the base URL for your Opsgenie integration, such
|
||||
as `https://app.opsgenie.com/alert/list`.
|
||||
1. Click **Save changes**.
|
||||
|
||||
After enabling the integration, navigate to the Alerts list page at **{cloud-gear}** **Operations > Alerts**, and click **View alerts in Opsgenie**.
|
||||
|
||||
### Enable a Generic Alerts endpoint
|
||||
|
||||
GitLab provides the Generic Alerts endpoint so you can accept alerts from a third-party
|
||||
alerts service. See the
|
||||
[instructions for toggling generic alerts](../../user/project/integrations/generic_alerts.md#setting-up-generic-alerts)
|
||||
to add this option. After configuring the endpoint, the
|
||||
[Alerts list](#alert-management-list) is enabled.
|
||||
|
||||
To populate the alerts with data, see [Customizing the payload](../../user/project/integrations/generic_alerts.md#customizing-the-payload) for requests to the alerts endpoint.
|
||||
|
||||
### Enable GitLab-managed Prometheus alerts
|
||||
|
||||
You can install the GitLab-managed Prometheus application on your Kubernetes
|
||||
cluster. For more information, see
|
||||
[Managed Prometheus on Kubernetes](../../user/project/integrations/prometheus.md#managed-prometheus-on-kubernetes).
|
||||
When GitLab-managed Prometheus is installed, the [Alerts list](#alert-management-list)
|
||||
is also enabled.
|
||||
|
||||
To populate the alerts with data, see
|
||||
[GitLab-Managed Prometheus instances](../metrics/alerts.md#managed-prometheus-instances).
|
||||
|
||||
### Enable external Prometheus alerts
|
||||
|
||||
You can configure an externally-managed Prometheus instance to send alerts
|
||||
to GitLab. To set up this configuration, see the [configuring Prometheus](../metrics/alerts.md#external-prometheus-instances) documentation. Activating the external Prometheus
|
||||
configuration also enables the [Alerts list](#alert-management-list).
|
||||
|
||||
To populate the alerts with data, see
|
||||
[External Prometheus instances](../metrics/alerts.md#external-prometheus-instances).
|
||||
|
||||
## Alert Management severity
|
||||
|
||||
Each level of alert contains a uniquely shaped and color-coded icon to help
|
||||
you identify the severity of a particular alert. These severity icons help you
|
||||
immediately identify which alerts you should prioritize investigating:
|
||||
|
||||
![Alert Management Severity System](img/alert_management_severity_v13_0.png)
|
||||
|
||||
Alerts contain one of the following icons:
|
||||
|
||||
| Severity | Icon | Color (hexadecimal) |
|
||||
|---|---|---|
|
||||
| Critical | **{severity-critical}** | `#8b2615` |
|
||||
| High | **{severity-high}** | `#c0341d` |
|
||||
| Medium | **{severity-medium}** | `#fca429` |
|
||||
| Low | **{severity-low}** | `#fdbc60` |
|
||||
| Info | **{severity-info}** | `#418cd8` |
|
||||
| Unknown | **{severity-unknown}** | `#bababa` |
|
||||
|
||||
## Alert Management list
|
||||
|
||||
NOTE: **Note:**
|
||||
You will need at least Developer [permissions](../../user/permissions.md) to view the Alert Management list.
|
||||
|
||||
You can find the Alert Management list at **{cloud-gear}** **Operations > Alerts** in your project's sidebar.
|
||||
Each alert contains the following metrics:
|
||||
|
||||
![Alert Management List](../../user/project/operations/img/alert_list_v13_1.png)
|
||||
|
||||
- **Severity** - The current importance of a alert and how much attention it should receive.
|
||||
- **Start time** - How long ago the alert fired. This field uses the standard GitLab pattern of `X time ago`, but is supported by a granular date/time tooltip depending on the user's locale.
|
||||
- **Alert description** - The description of the alert, which attempts to capture the most meaningful data.
|
||||
- **Event count** - The number of times that an alert has fired.
|
||||
- **Issue** - A link to the incident issue that has been created for the alert.
|
||||
- **Status** - The [current status](#alert-management-statuses) of the alert.
|
||||
|
||||
### Alert Management list sorting
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217745) in GitLab 13.1.
|
||||
|
||||
The Alert Management list displays alerts sorted by start time, but you can
|
||||
change the sort order by clicking the headers in the Alert Management list.
|
||||
|
||||
To see if a column is sortable, point your mouse at the header. Sortable columns
|
||||
display an arrow next to the column name, as shown in this example:
|
||||
|
||||
![Alert Management List Sorting](img/alert_list_sort_v13_1.png)
|
||||
|
||||
### Searching alerts
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213884) in GitLab 13.1.
|
||||
|
||||
The alert list supports a simple free text search.
|
||||
|
||||
![Alert List Search](img/alert_list_search_v13_1.png)
|
||||
|
||||
This search filters on the following fields:
|
||||
|
||||
- Title
|
||||
- Description
|
||||
- Monitoring tool
|
||||
- Service
|
||||
|
||||
### Alert Management statuses
|
||||
|
||||
Each alert contains a status dropdown to indicate which alerts need investigation.
|
||||
Standard alert statuses include `triggered`, `acknowledged`, and `resolved`:
|
||||
|
||||
- **Triggered**: No one has begun investigation.
|
||||
- **Acknowledged**: Someone is actively investigating the problem.
|
||||
- **Resolved**: No further work is required.
|
||||
|
||||
## Alert Management details
|
||||
|
||||
NOTE: **Note:**
|
||||
You will need at least Developer [permissions](../../user/permissions.md) to view Alert Management details.
|
||||
|
||||
Navigate to the Alert Management detail view by visiting the [Alert Management list](#alert-management-list) and selecting an Alert from the list.
|
||||
|
||||
![Alert Management Detail Overview](img/alert_detail_overview_v13_1.png)
|
||||
|
||||
![Alert Management Full Details](img/alert_detail_full_v13_1.png)
|
||||
|
||||
### Update an Alert's status
|
||||
|
||||
The Alert Management detail view enables you to update the Alert Status.
|
||||
See [Alert Management statuses](#alert-management-statuses) for more details.
|
||||
|
||||
### Create an Issue from an Alert
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217745) in GitLab 13.1.
|
||||
|
||||
The Alert Management detail view enables you to create an issue with a
|
||||
description automatically populated from an alert. To create the issue,
|
||||
click the **Create Issue** button. You can then view the issue from the
|
||||
alert by clicking the **View Issue** button.
|
||||
|
||||
Closing a GitLab issue associated with an alert changes the alert's status to Resolved.
|
||||
See [Alert Management statuses](#alert-management-statuses) for more details about statuses.
|
||||
|
||||
### Update an Alert's assignee
|
||||
|
||||
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3066) in GitLab 13.1.
|
||||
|
||||
The Alert Management detail view allows users to update the Alert assignee.
|
||||
|
||||
In large teams, where there is shared ownership of an alert, it can be difficult
|
||||
to track who is investigating and working on it. The Alert Management detail view
|
||||
enables you to update the Alert assignee:
|
||||
|
||||
NOTE: **Note:**
|
||||
GitLab currently only supports a single assignee per alert.
|
||||
|
||||
1. To display the list of current alerts, click
|
||||
**{cloud-gear}** **Operations > Alerts**:
|
||||
|
||||
![Alert Management List View Assignee(s)](img/alert_list_assignees_v13_1.png)
|
||||
|
||||
1. Select your desired alert to display its **Alert Management Details View**:
|
||||
|
||||
![Alert Management Details View Assignee(s)](img/alert_details_assignees_v13_1.png)
|
||||
|
||||
1. If the right sidebar is not expanded, click
|
||||
**{angle-double-right}** **Expand sidebar** to expand it.
|
||||
1. In the right sidebar, locate the **Assignee** and click **Edit**. From the
|
||||
dropdown menu, select each user you want to assign to the alert. GitLab creates
|
||||
a [To-Do list item](../../user/todos.md) for each user.
|
||||
|
||||
![Alert Management Details View Assignee(s)](img/alert_todo_assignees_v13_1.png)
|
||||
|
||||
To remove an assignee, click **Edit** next to the **Assignee** dropdown menu and
|
||||
deselect the user from the list of assignees, or click **Unassigned**.
|
||||
|
||||
### Alert system notes
|
||||
|
||||
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3066) in GitLab 13.1.
|
||||
|
||||
When you take action on an alert, this is logged as a system note,
|
||||
which is visible in the Alert Details view. This gives you a linear
|
||||
timeline of the alert's investigation and assignment history.
|
||||
|
||||
The following actions will result in a system note:
|
||||
|
||||
- [Updating the status of an alert](#update-an-alerts-status)
|
||||
- [Creating an issue based on an alert](#create-an-issue-from-an-alert)
|
||||
- [Assignment of an alert to a user](#update-an-alerts-assignee)
|
||||
|
||||
![Alert Management Details View System Notes](img/alert_detail_system_notes_v13_1.png)
|
||||
|
||||
### Create a To-Do from an Alert
|
||||
|
||||
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3066) in GitLab 13.1.
|
||||
|
||||
You can manually create [To-Do list items](../../user/todos.md) for yourself from the
|
||||
Alert details screen, and view them later on your **To-Do List**. To add a To-Do:
|
||||
|
||||
1. To display the list of current alerts, click
|
||||
**{cloud-gear}** **Operations > Alerts**.
|
||||
1. Select your desired alert to display its **Alert Management Details View**.
|
||||
1. Click the **Add a To-Do** button in the right sidebar:
|
||||
|
||||
![Alert Management Details Add A To Do](img/alert_detail_add_todo_v13_1.png)
|
||||
|
||||
Click the **To-Do** **{todo-done}** in the navigation bar to view your current To-Do list.
|
||||
|
||||
![Alert Management Details Added to Do](img/alert_detail_added_todo_v13_1.png)
|
||||
|
||||
### View an Alert's metrics data
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217768) in GitLab 13.2.
|
||||
|
||||
To view the metrics for an alert:
|
||||
|
||||
1. Sign in as a user with Developer or higher [permissions](../../user/permissions.md).
|
||||
1. Navigate to **{cloud-gear}** **Operations > Alerts**.
|
||||
1. Click the alert you want to view.
|
||||
1. Below the title of the alert, click the **Metrics** tab.
|
||||
|
||||
![Alert Management Metrics View](img/alert_detail_metrics_v13_2.png)
|
||||
|
||||
For GitLab-managed Prometheus instances, metrics data is automatically available
|
||||
for the alert, making it easy to see surrounding behavior. See
|
||||
[Managed Prometheus instances](../metrics/alerts.md#managed-prometheus-instances)
|
||||
for information on setting up alerts.
|
||||
|
||||
For externally-managed Prometheus instances, you can configure your alerting rules to
|
||||
display a chart in the alert. See
|
||||
[Embedding metrics based on alerts in incident issues](../metrics/embed.md#embedding-metrics-based-on-alerts-in-incident-issues)
|
||||
for information on how to appropriately configure your alerting rules. See
|
||||
[External Prometheus instances](../metrics/alerts.md#external-prometheus-instances)
|
||||
for information on setting up alerts for your self-managed Prometheus instance.
|
||||
|
||||
### View an Alert's logs
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217768) in GitLab 13.3.
|
||||
|
||||
To view the logs for an alert:
|
||||
|
||||
1. Sign in as a user with Developer or higher [permissions](../../user/permissions.md).
|
||||
1. Navigate to **{cloud-gear}** **Operations > Alerts**.
|
||||
1. Click the alert you want to view.
|
||||
1. Below the title of the alert, click the **Metrics** tab.
|
||||
1. Click the [menu](../metrics/dashboards/index.md#chart-context-menu) of the metric chart to view options.
|
||||
1. Click **View logs**.
|
||||
|
||||
Read [View logs from metrics panel](#view-logs-from-metrics-panel) for additional information.
|
||||
|
||||
## Use cases for assigning alerts
|
||||
|
||||
Consider a team formed by different sections of monitoring, collaborating on a
|
||||
single application. After an alert surfaces, it's extremely important to
|
||||
route the alert to the team members who can address and resolve the alert.
|
||||
|
||||
Assigning Alerts to multiple assignees eases collaboration and delegation. All
|
||||
assignees are shown in your team's work-flows, and all assignees receive
|
||||
notifications, simplifying communication and ownership of the alert.
|
||||
|
||||
After completing their portion of investigating or fixing the alert, users can
|
||||
unassign their account from the alert when their role is complete.
|
||||
The [alerts status](#alert-management-statuses) can be updated to
|
||||
reflect if the alert has been resolved.
|
||||
## Alert notifications
|
||||
|
||||
### Slack Notifications
|
||||
|
||||
|
@ -341,36 +26,6 @@ You can be alerted via a Slack message when a new alert has been received.
|
|||
|
||||
See the [Slack Notifications Service docs](../../user/project/integrations/slack.md) for information on how to set this up.
|
||||
|
||||
## Configure incidents
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/4925) in GitLab Ultimate 11.11.
|
||||
|
||||
With Maintainer or higher [permissions](../../user/permissions.md), you can enable or disable Incident Management features in the GitLab user interface
|
||||
to create issues when alerts are triggered:
|
||||
|
||||
1. Navigate to **Settings > Operations > Incidents** and expand
|
||||
**Incidents**:
|
||||
|
||||
![Incident Management Settings](img/incident_management_settings_v13_3.png)
|
||||
|
||||
1. For GitLab versions 11.11 and greater, you can select the **Create an issue**
|
||||
checkbox to create an issue based on your own
|
||||
[issue templates](../../user/project/description_templates.md#creating-issue-templates).
|
||||
For more information, see
|
||||
[Trigger actions from alerts](../metrics/alerts.md#trigger-actions-from-alerts-ultimate) **(ULTIMATE)**.
|
||||
1. To create issues from alerts, select the template in the **Issue Template**
|
||||
select box.
|
||||
1. To send [separate email notifications](#notify-developers-of-alerts) to users
|
||||
with [Developer permissions](../../user/permissions.md), select
|
||||
**Send a separate email notification to Developers**.
|
||||
1. Click **Save changes**.
|
||||
|
||||
Appropriately configured alerts include an
|
||||
[embedded chart](../metrics/embed.md#embedding-metrics-based-on-alerts-in-incident-issues)
|
||||
for the query corresponding to the alert. You can also configure GitLab to
|
||||
[close issues](../metrics/alerts.md#trigger-actions-from-alerts-ultimate)
|
||||
when you receive notification that the alert is resolved.
|
||||
|
||||
### Notify developers of alerts
|
||||
|
||||
GitLab can react to the alerts triggered from your applications and services
|
||||
|
@ -379,58 +34,8 @@ sends these emails to [owners and maintainers](../../user/permissions.md) of the
|
|||
These emails contain details of the alert, and a link for more information.
|
||||
|
||||
To send separate email notifications to users with
|
||||
[Developer permissions](../../user/permissions.md), see [Configure incidents](#configure-incidents).
|
||||
|
||||
## Incident List
|
||||
|
||||
Incidents in GitLab are aggregated in the Incident List, available at
|
||||
**Operations > Incidents**. This list displays all incidents in GitLab, with tabs
|
||||
to display open incidents, closed incidents, and all incidents:
|
||||
|
||||
![Incident list](img/incident_list.png)
|
||||
|
||||
The list displays the following attributes:
|
||||
|
||||
- **Incident title**
|
||||
- **Date created** - in 'time ago' format.
|
||||
- **Assignees** - the avatar of the user assigned to the incident.
|
||||
- **Published** - Displays a green check mark (**{check-circle}**) if the incident is published
|
||||
to a [Status Page](status_page.md).
|
||||
|
||||
## Create an incident manually
|
||||
|
||||
> [Moved](https://gitlab.com/gitlab-org/monitor/health/-/issues/24) to GitLab core in 13.3.
|
||||
|
||||
For users with at least Developer [permissions](../../user/permissions.md), to create a Incident you can take any of the following actions:
|
||||
|
||||
- Navigate to **Operations > Incidents** and click **Create Incident**.
|
||||
- Create a new issue using the `incident` template available when creating it.
|
||||
- Create a new issue and assign the `incident` label to it.
|
||||
|
||||
![Incident List Create](img/incident_list_create_v13_3.png)
|
||||
|
||||
## Configure PagerDuty integration
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/119018) in GitLab 13.3.
|
||||
|
||||
You can set up a webhook with PagerDuty to automatically create a GitLab issue
|
||||
for each PagerDuty incident. This configuration requires you to make changes
|
||||
in both PagerDuty and GitLab:
|
||||
|
||||
1. Sign in as a user with Maintainer [permissions](../../user/permissions.md).
|
||||
1. Navigate to **Settings > Operations > Incidents** and expand **Incidents**.
|
||||
1. Select the **PagerDuty integration** tab:
|
||||
|
||||
![PagerDuty incidents integration](img/pagerduty_incidents_integration_v13_3.png)
|
||||
|
||||
1. Activate the integration, and save the changes in GitLab.
|
||||
1. Copy the value of **Webhook URL** for use in a later step.
|
||||
1. Follow the steps described in the
|
||||
[PagerDuty documentation](https://support.pagerduty.com/docs/webhooks)
|
||||
to add the webhook URL to a PagerDuty webhook integration.
|
||||
|
||||
To confirm the integration is successful, trigger a test incident from PagerDuty to
|
||||
confirm that a GitLab issue is created from the incident.
|
||||
[Developer permissions](../../user/permissions.md), see
|
||||
[Configure incidents](incidents.md#configure-incidents).
|
||||
|
||||
## Configure Prometheus alerts
|
||||
|
||||
|
@ -448,36 +53,6 @@ GitLab can accept alerts from any source through a generic webhook receiver. Whe
|
|||
[configuring the generic alerts integration](../../user/project/integrations/generic_alerts.md),
|
||||
GitLab creates a unique endpoint which receives a JSON-formatted, customizable payload.
|
||||
|
||||
## Embed metrics in incidents and issues
|
||||
|
||||
You can embed metrics anywhere [GitLab Markdown](../../user/markdown.md) is used, such as descriptions,
|
||||
comments on issues, and merge requests. Embedding metrics helps you share them
|
||||
when discussing incidents or performance issues. You can output the dashboard directly
|
||||
into any issue, merge request, epic, or any other Markdown text field in GitLab
|
||||
by [copying and pasting the link to the metrics dashboard](../metrics/embed.md#embedding-gitlab-managed-kubernetes-metrics).
|
||||
|
||||
You can embed both
|
||||
[GitLab-hosted metrics](../metrics/embed.md) and
|
||||
[Grafana metrics](../metrics/embed_grafana.md)
|
||||
in incidents and issue templates.
|
||||
|
||||
### Context menu
|
||||
|
||||
You can view more details about an embedded metrics panel from the context menu.
|
||||
To access the context menu, click the **{ellipsis_v}** **More actions** dropdown box
|
||||
above the upper right corner of the panel. For a list of options, see
|
||||
[Chart context menu](../metrics/dashboards/index.md#chart-context-menu).
|
||||
|
||||
#### View logs from metrics panel
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/201846) in GitLab Ultimate 12.8.
|
||||
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25455) to [GitLab Core](https://about.gitlab.com/pricing/) 12.9.
|
||||
|
||||
Viewing logs from a metrics panel can be useful if you're triaging an application
|
||||
incident and need to [explore logs](../metrics/dashboards/index.md#chart-context-menu)
|
||||
from across your application. These logs help you understand what is affecting
|
||||
your application's performance and resolve any problems.
|
||||
|
||||
## Integrate incidents with Slack
|
||||
|
||||
Slack slash commands allow you to control GitLab and view GitLab content without leaving Slack.
|
||||
|
|
|
@ -89,8 +89,8 @@ is no longer used.
|
|||
| `id` | string | no | Used for associating dashboard metrics with database records. Must be unique across dashboard configuration files. Required for [alerting](../alerts.md) (support not yet enabled, see [relevant issue](https://gitlab.com/gitlab-org/gitlab/-/issues/27980)). |
|
||||
| `unit` | string | yes | Defines the unit of the query's return data. |
|
||||
| `label` | string | no, but highly encouraged | Defines the legend-label for the query. Should be unique within the panel's metrics. Can contain time series labels as interpolated variables. |
|
||||
| `query` | string | yes if `query_range` is not defined | Defines the Prometheus query to be used to populate the chart/panel. If defined, the `query` endpoint of the [Prometheus API](https://prometheus.io/docs/prometheus/latest/querying/api/) will be utilized. |
|
||||
| `query_range` | string | yes if `query` is not defined | Defines the Prometheus query to be used to populate the chart/panel. If defined, the `query_range` endpoint of the [Prometheus API](https://prometheus.io/docs/prometheus/latest/querying/api/) will be utilized. |
|
||||
| `query` | string/number | yes if `query_range` is not defined | Defines the Prometheus query to be used to populate the chart/panel. If defined, the `query` endpoint of the [Prometheus API](https://prometheus.io/docs/prometheus/latest/querying/api/) will be utilized. |
|
||||
| `query_range` | string/number | yes if `query` is not defined | Defines the Prometheus query to be used to populate the chart/panel. If defined, the `query_range` endpoint of the [Prometheus API](https://prometheus.io/docs/prometheus/latest/querying/api/) will be utilized. |
|
||||
| `step` | number | no, value is calculated if not defined | Defines query resolution step width in float number of seconds. Metrics on the same panel should use the same `step` value. |
|
||||
|
||||
## Dynamic labels
|
||||
|
@ -156,21 +156,46 @@ and files with invalid syntax display **Metrics Dashboard YAML definition is inv
|
|||
|
||||
When **Metrics Dashboard YAML definition is invalid** at least one of the following messages is displayed:
|
||||
|
||||
1. `dashboard: can't be blank` [learn more](#dashboard-top-level-properties)
|
||||
1. `panel_groups: should be an array of panel_groups objects` [learn more](#dashboard-top-level-properties)
|
||||
1. `group: can't be blank` [learn more](#panel-group-panel_groups-properties)
|
||||
1. `panels: should be an array of panels objects` [learn more](#panel-group-panel_groups-properties)
|
||||
1. `title: can't be blank` [learn more](#panel-panels-properties)
|
||||
1. `metrics: should be an array of metrics objects` [learn more](#panel-panels-properties)
|
||||
1. `query: can't be blank` [learn more](#metrics-metrics-properties)
|
||||
1. `query_range: can't be blank` [learn more](#metrics-metrics-properties)
|
||||
1. `unit: can't be blank` [learn more](#metrics-metrics-properties)
|
||||
1. `YAML syntax: The parsed YAML is too big`
|
||||
1. `[location] is missing required keys: [list of missing keys]` - The entry at
|
||||
`[location]` is missing a key, or a key has been mistyped. This
|
||||
example returns the error `root is missing required keys: panel_groups`:
|
||||
|
||||
This is displayed when the YAML file is larger than 1 MB.
|
||||
```yaml
|
||||
dashboard: Important metrics
|
||||
group_panels:
|
||||
- ...
|
||||
```
|
||||
|
||||
1. `YAML syntax: Invalid configuration format`
|
||||
1. `[data] at [location] is not of type: [type]` - The entry at `[location]` contains
|
||||
`[data]` which type does not adhere to required types. This example returns the
|
||||
error `'123' at /panel_groups/0/group is not of type: string`:
|
||||
|
||||
This is displayed when the YAML file is empty or does not contain valid YAML.
|
||||
```yaml
|
||||
dashboard: Environment metrics
|
||||
panel_groups:
|
||||
- group: 123
|
||||
panels:
|
||||
...
|
||||
```
|
||||
|
||||
1. `[data] at [location] is not one of: [types]` - The entry at `[location]` contains
|
||||
`[data]` which is not included in the list of required values. This example returns
|
||||
the error `'scatterplot-chart' at /panel_groups/0/panels/0/type is not one of: ["area-chart", "line-chart", "anomaly-chart", "bar", "column", "stacked-column", "single-stat", "heatmap"]`:
|
||||
|
||||
```yaml
|
||||
dashboard: Environment metrics
|
||||
panel_groups:
|
||||
- group: Network
|
||||
panels:
|
||||
- title: Throughput
|
||||
type: scatterplot-chart
|
||||
y_label: Requests / Sec
|
||||
...
|
||||
```
|
||||
|
||||
1. `metric_id must be unique across a project` - At least two metrics entries have
|
||||
the same `id` attribute, which [must be unique](#metrics-metrics-properties).
|
||||
1. `The parsed YAML is too big` - The YAML file is larger than 1 MB.
|
||||
1. `Invalid configuration format` - The YAML file is empty or does not contain valid YAML.
|
||||
|
||||
Metrics Dashboard YAML definition validation information is also available as a [GraphQL API field](../../../api/graphql/reference/index.md#metricsdashboard)
|
||||
|
|
|
@ -116,7 +116,7 @@ In GitLab versions 13.2 and greater, GitLab groups alerts based on their payload
|
|||
When an incoming alert contains the same payload as another alert (excluding the
|
||||
`start_time` and `hosts` attributes), GitLab groups these alerts together and
|
||||
displays a counter on the
|
||||
[Alert Management List](../../../operations/incident_management/index.md#alert-management-list)
|
||||
[Alert Management List](../../../operations/incident_management/incidents.md)
|
||||
and details pages.
|
||||
|
||||
If the existing alert is already `resolved`, then a new alert will be created instead.
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 37 KiB |
Binary file not shown.
Before Width: | Height: | Size: 11 KiB |
|
@ -18,7 +18,7 @@ You can find the available integrations under your project's
|
|||
There are more than 20 integrations to integrate with. Click on the one that you
|
||||
want to configure.
|
||||
|
||||
![Integrations list](img/project_services.png)
|
||||
![Integrations list](img/project_integrations_v13_3.png)
|
||||
|
||||
## Integrations listing
|
||||
|
||||
|
|
|
@ -24,8 +24,6 @@ module Gitlab
|
|||
end
|
||||
|
||||
def create_partitions
|
||||
return unless Feature.enabled?(:postgres_dynamic_partition_creation, default_enabled: true)
|
||||
|
||||
Gitlab::AppLogger.info("Checking state of dynamic postgres partitions")
|
||||
|
||||
models.each do |model|
|
||||
|
|
|
@ -59,6 +59,9 @@ module Gitlab
|
|||
},
|
||||
contact_sales_btn_in_app: {
|
||||
tracking_category: 'Growth::Conversion::Experiment::ContactSalesInApp'
|
||||
},
|
||||
customize_homepage: {
|
||||
tracking_category: 'Growth::Expansion::Experiment::CustomizeHomepage'
|
||||
}
|
||||
}.freeze
|
||||
|
||||
|
|
|
@ -76,6 +76,102 @@
|
|||
- "< 1 saat"
|
||||
- "< 1 Stunde"
|
||||
- "< 1시간"
|
||||
|
||||
#
|
||||
# Strings below are fixed in the source code but the translations are still present in CrowdIn so the
|
||||
# locale files will fail the linter. They can be deleted after next CrowdIn sync, likely in:
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/issues/226008
|
||||
#
|
||||
|
||||
"This commit was signed with an <strong>unverified</strong> signature.":
|
||||
plural_id:
|
||||
translations:
|
||||
- "このコミットは<strong>検証されていない</strong> 署名でサインされています。"
|
||||
- "Этот коммит был подписан <strong>непроверенной</strong> подписью."
|
||||
- "此提交使用 <strong>未经验证的</strong> 签名进行签名。"
|
||||
- "Цей коміт підписано <strong>неперевіреним</strong> підписом."
|
||||
- "Esta commit fue firmado con una firma <strong>no verificada</strong>."
|
||||
"This commit was signed with a <strong>verified</strong> signature and the committer email is verified to belong to the same user.":
|
||||
plural_id:
|
||||
translations:
|
||||
- "このコミットは <strong>検証済み</strong> の署名でサインされており、このコミッターのメールは同じユーザーのものであることが検証されています。"
|
||||
- "Это коммит был подписан <strong>верифицированной</strong> подписью и коммитер подтвердил, что адрес почты принадлежит ему."
|
||||
- "此提交使用 <strong>已验证</strong> 的签名进行签名,并且已验证提交者的电子邮件属于同一用户。"
|
||||
- "Цей коміт підписано <strong>перевіреним</strong> підписом і адреса електронної пошти комітера гарантовано належить тому самому користувачу."
|
||||
- "Este commit fue firmado con una firma verificada, y <strong>se ha verificado</strong> que la dirección de correo electrónico del committer y la firma pertenecen al mismo usuario."
|
||||
"Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}":
|
||||
plural_id:
|
||||
translations:
|
||||
- "分支 <strong>%{branch_name}</strong> 已創建。如需設置自動部署, 請選擇合適的 GitLab CI Yaml 模板併提交更改。%{link_to_autodeploy_doc}"
|
||||
- "O branch <strong>%{branch_name}</strong> foi criado. Para configurar o deploy automático, selecione um modelo de Yaml do GitLab CI e commit suas mudanças. %{link_to_autodeploy_doc}"
|
||||
- "<strong>%{branch_name}</strong> ブランチが作成されました。自動デプロイを設定するには、GitLab CI Yaml テンプレートを選択して、変更をコミットしてください。 %{link_to_autodeploy_doc}"
|
||||
- "La branch <strong>%{branch_name}</strong> è stata creata. Per impostare un rilascio automatico scegli un template CI di Gitlab e committa le tue modifiche %{link_to_autodeploy_doc}"
|
||||
- "O ramo <strong>%{branch_name}</strong> foi criado. Para configurar a implantação automática, seleciona um modelo de Yaml do GitLab CI e envia as tuas alterações. %{link_to_autodeploy_doc}"
|
||||
- "Ветка <strong>%{branch_name}</strong> создана. Для настройки автоматического развертывания выберите YAML-шаблон для GitLab CI и зафиксируйте свои изменения. %{link_to_autodeploy_doc}"
|
||||
- "已创建分支 <strong>%{branch_name}</strong> 。如需设置自动部署, 请选择合适的 GitLab CI Yaml 模板并提交更改。%{link_to_autodeploy_doc}"
|
||||
- "Гілка <strong>%{branch_name}</strong> створена. Для настройки автоматичного розгортання виберіть GitLab CI Yaml-шаблон і закомітьте зміни. %{link_to_autodeploy_doc}"
|
||||
- "Клонът <strong>%{branch_name}</strong> беше създаден. За да настроите автоматичното внедряване, изберете Yaml шаблон за GitLab CI и подайте промените си. %{link_to_autodeploy_doc}"
|
||||
- "Branch <strong>%{branch_name}</strong> wurde erstellt. Um die automatische Bereitstellung einzurichten, wähle eine GitLab CI Yaml Vorlage und committe deine Änderungen. %{link_to_autodeploy_doc}"
|
||||
- "<strong>%{branch_name}</strong> 브랜치가 생성되었습니다. 자동 배포를 설정하려면 GitLab CI Yaml 템플릿을 선택하고 변경 사항을 적용하십시오. %{link_to_autodeploy_doc}"
|
||||
- "La branĉo <strong>%{branch_name}</strong> estis kreita. Por agordi aŭtomatan disponigadon, bonvolu elekti Yaml-ŝablonon por GitLab CI kaj enmeti viajn ŝanĝojn. %{link_to_autodeploy_doc}"
|
||||
- "La branche <strong>%{branch_name}</strong> a été créée. Pour mettre en place le déploiement automatisé, sélectionnez un modèle de fichier YAML pour l’intégration continue (CI) de GitLab, et validez les modifications. %{link_to_autodeploy_doc}"
|
||||
- "La rama <strong>%{branch_name}</strong> fue creada. Para configurar el auto despliegue, escoge una plantilla Yaml para GitLab CI y envía tus cambios. %{link_to_autodeploy_doc}"
|
||||
"GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page.":
|
||||
plural_id:
|
||||
translations:
|
||||
- "GitLab Pagesはこのプロジェクトでは無効になっています。 プロジェクトの%{strong_start} 設定> 全般> 可視性%{strong_end}ページで有効にできます。"
|
||||
- "GitLab Pages отключены для этого проекта. Вы можете включить в поле %{strong_start}Настройки > Общие > Видимость%{strong_end} вашего проекта."
|
||||
- "此项目禁用GitLab Pages。您可以在您的项目的%{strong_start}设置 > 常规 > 可见性%{strong_end} 页面启用。"
|
||||
- "GitLab Pages вимкнено для цього проєкту. Ви можете їх увімкнути перейшовши на сторінку проєкту %{strong_start}Налаштування > Загальні > Видимість%{strong_end}."
|
||||
- "Las páginas de GitLab están deshabilitadas para este proyecto. Puede habilitarlas en los ajustes %{strong_start} de su proyecto > General > Visibilidad%{strong_end}."
|
||||
"You can invite a new member to <strong>%{project_name}</strong> or invite another group.":
|
||||
plural_id:
|
||||
translations:
|
||||
- "新しいメンバーを<strong>%{project_name} </strong>に招待するか、別のグループを招待することができます。"
|
||||
- "Podes convidar um novo para <strong>%{project_name}</strong> ou convidar outro grupo."
|
||||
- "邀请新成员或另一个群组加入<strong>%{project_name}</strong>。"
|
||||
- "Puede invitar a un nuevo miembro a <strong>%{project_name}</strong> o invitar a otro grupo."
|
||||
- "<strong>%{project_name}</strong> projesine yeni bir üye davet edebilir veya başka bir grubu davet edebilirsiniz."
|
||||
- "Вы можете пригласить нового участника в <strong>%{project_name}</strong> или пригласить другую группу."
|
||||
- "Ви можете запросити нового учасника до <strong>%{project_name}</strong> або запросити іншу групу."
|
||||
"You can invite a new member to <strong>%{project_name}</strong>.":
|
||||
plural_id:
|
||||
translations:
|
||||
- "新しいメンバーを<strong>%{project_name} </strong>に招待できます。"
|
||||
- "Podes convidar um novo membro para <strong>%{project_name}</strong>."
|
||||
- "邀请新成员加入<strong>%{project_name}</strong>。"
|
||||
- "Puedes invitar a un nuevo miembro a <strong>%{project_name}</strong>."
|
||||
- "<strong>%{project_name}</strong> projesine yeni bir üye davet edebilirsiniz."
|
||||
- "Вы можете пригласить нового участника в <strong>%{project_name}</strong>."
|
||||
- "Ви можете запросити нового учасника до <strong>%{project_name}</strong>."
|
||||
"You can invite another group to <strong>%{project_name}</strong>.":
|
||||
plural_id:
|
||||
translations:
|
||||
- "他のグループを<strong>%{project_name} </strong>に招待できます。"
|
||||
- "Podes convidar outro grupo para <strong>%{project_name}</strong>."
|
||||
- "您可以邀请另一个群组加入<strong>%{project_name}</strong>。"
|
||||
- "Ви можете запросити нову групу до <strong>%{project_name}</strong>."
|
||||
- "Puedes invitar a otro grupo a <strong>%{project_name}</strong>."
|
||||
"Example: <code>192.168.0.0/24</code>. %{read_more_link}.":
|
||||
plural_id:
|
||||
translations:
|
||||
"Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\\\"%{pg_version_upcoming_url}\\\">the related epic</a> for details.":
|
||||
plural_id:
|
||||
translations:
|
||||
"Authorize <strong>%{user}</strong> to use your account?":
|
||||
plural_id:
|
||||
translations:
|
||||
"DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}.":
|
||||
plural_id:
|
||||
translations:
|
||||
"<project name>":
|
||||
translations:
|
||||
- "<название проекта>"
|
||||
- "<project name>"
|
||||
- "<proje adı>"
|
||||
- "<naziv projekta>"
|
||||
- "<ім’я проєкту>"
|
||||
- "<프로젝트 이름>"
|
||||
"<strong>Deletes</strong> source branch":
|
||||
plural_id:
|
||||
translations:
|
||||
|
@ -217,99 +313,3 @@
|
|||
- "Vous êtes sur le point de d’activer la confidentialité. Cela signifie que seuls les membres de l’équipe avec <strong>au moins un accès en tant que rapporteur</strong> seront en mesure de voir et de laisser des commentaires sur le ticket."
|
||||
- "Va a activar la confidencialidad. Esto significa que solo los miembros del equipo con como mínimo,<strong>acceso como Reporter</strong> podrán ver y dejar comentarios sobre la incidencia."
|
||||
- "あなたは非公開設定をオンにしようとしています。これは、最低でも<strong>報告権限</strong>を持ったチームメンバーのみが課題を表示したりコメントを残したりすることができるようになるということです。"
|
||||
|
||||
#
|
||||
# Strings below are fixed in the source code but the translations are still present in CrowdIn so the
|
||||
# locale files will fail the linter. They can be deleted after next CrowdIn sync, likely in:
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/issues/226008
|
||||
#
|
||||
|
||||
"This commit was signed with an <strong>unverified</strong> signature.":
|
||||
plural_id:
|
||||
translations:
|
||||
- "このコミットは<strong>検証されていない</strong> 署名でサインされています。"
|
||||
- "Этот коммит был подписан <strong>непроверенной</strong> подписью."
|
||||
- "此提交使用 <strong>未经验证的</strong> 签名进行签名。"
|
||||
- "Цей коміт підписано <strong>неперевіреним</strong> підписом."
|
||||
- "Esta commit fue firmado con una firma <strong>no verificada</strong>."
|
||||
"This commit was signed with a <strong>verified</strong> signature and the committer email is verified to belong to the same user.":
|
||||
plural_id:
|
||||
translations:
|
||||
- "このコミットは <strong>検証済み</strong> の署名でサインされており、このコミッターのメールは同じユーザーのものであることが検証されています。"
|
||||
- "Это коммит был подписан <strong>верифицированной</strong> подписью и коммитер подтвердил, что адрес почты принадлежит ему."
|
||||
- "此提交使用 <strong>已验证</strong> 的签名进行签名,并且已验证提交者的电子邮件属于同一用户。"
|
||||
- "Цей коміт підписано <strong>перевіреним</strong> підписом і адреса електронної пошти комітера гарантовано належить тому самому користувачу."
|
||||
- "Este commit fue firmado con una firma verificada, y <strong>se ha verificado</strong> que la dirección de correo electrónico del committer y la firma pertenecen al mismo usuario."
|
||||
"Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}":
|
||||
plural_id:
|
||||
translations:
|
||||
- "分支 <strong>%{branch_name}</strong> 已創建。如需設置自動部署, 請選擇合適的 GitLab CI Yaml 模板併提交更改。%{link_to_autodeploy_doc}"
|
||||
- "O branch <strong>%{branch_name}</strong> foi criado. Para configurar o deploy automático, selecione um modelo de Yaml do GitLab CI e commit suas mudanças. %{link_to_autodeploy_doc}"
|
||||
- "<strong>%{branch_name}</strong> ブランチが作成されました。自動デプロイを設定するには、GitLab CI Yaml テンプレートを選択して、変更をコミットしてください。 %{link_to_autodeploy_doc}"
|
||||
- "La branch <strong>%{branch_name}</strong> è stata creata. Per impostare un rilascio automatico scegli un template CI di Gitlab e committa le tue modifiche %{link_to_autodeploy_doc}"
|
||||
- "O ramo <strong>%{branch_name}</strong> foi criado. Para configurar a implantação automática, seleciona um modelo de Yaml do GitLab CI e envia as tuas alterações. %{link_to_autodeploy_doc}"
|
||||
- "Ветка <strong>%{branch_name}</strong> создана. Для настройки автоматического развертывания выберите YAML-шаблон для GitLab CI и зафиксируйте свои изменения. %{link_to_autodeploy_doc}"
|
||||
- "已创建分支 <strong>%{branch_name}</strong> 。如需设置自动部署, 请选择合适的 GitLab CI Yaml 模板并提交更改。%{link_to_autodeploy_doc}"
|
||||
- "Гілка <strong>%{branch_name}</strong> створена. Для настройки автоматичного розгортання виберіть GitLab CI Yaml-шаблон і закомітьте зміни. %{link_to_autodeploy_doc}"
|
||||
- "Клонът <strong>%{branch_name}</strong> беше създаден. За да настроите автоматичното внедряване, изберете Yaml шаблон за GitLab CI и подайте промените си. %{link_to_autodeploy_doc}"
|
||||
- "Branch <strong>%{branch_name}</strong> wurde erstellt. Um die automatische Bereitstellung einzurichten, wähle eine GitLab CI Yaml Vorlage und committe deine Änderungen. %{link_to_autodeploy_doc}"
|
||||
- "<strong>%{branch_name}</strong> 브랜치가 생성되었습니다. 자동 배포를 설정하려면 GitLab CI Yaml 템플릿을 선택하고 변경 사항을 적용하십시오. %{link_to_autodeploy_doc}"
|
||||
- "La branĉo <strong>%{branch_name}</strong> estis kreita. Por agordi aŭtomatan disponigadon, bonvolu elekti Yaml-ŝablonon por GitLab CI kaj enmeti viajn ŝanĝojn. %{link_to_autodeploy_doc}"
|
||||
- "La branche <strong>%{branch_name}</strong> a été créée. Pour mettre en place le déploiement automatisé, sélectionnez un modèle de fichier YAML pour l’intégration continue (CI) de GitLab, et validez les modifications. %{link_to_autodeploy_doc}"
|
||||
- "La rama <strong>%{branch_name}</strong> fue creada. Para configurar el auto despliegue, escoge una plantilla Yaml para GitLab CI y envía tus cambios. %{link_to_autodeploy_doc}"
|
||||
"GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page.":
|
||||
plural_id:
|
||||
translations:
|
||||
- "GitLab Pagesはこのプロジェクトでは無効になっています。 プロジェクトの%{strong_start} 設定> 全般> 可視性%{strong_end}ページで有効にできます。"
|
||||
- "GitLab Pages отключены для этого проекта. Вы можете включить в поле %{strong_start}Настройки > Общие > Видимость%{strong_end} вашего проекта."
|
||||
- "此项目禁用GitLab Pages。您可以在您的项目的%{strong_start}设置 > 常规 > 可见性%{strong_end} 页面启用。"
|
||||
- "GitLab Pages вимкнено для цього проєкту. Ви можете їх увімкнути перейшовши на сторінку проєкту %{strong_start}Налаштування > Загальні > Видимість%{strong_end}."
|
||||
- "Las páginas de GitLab están deshabilitadas para este proyecto. Puede habilitarlas en los ajustes %{strong_start} de su proyecto > General > Visibilidad%{strong_end}."
|
||||
"You can invite a new member to <strong>%{project_name}</strong> or invite another group.":
|
||||
plural_id:
|
||||
translations:
|
||||
- "新しいメンバーを<strong>%{project_name} </strong>に招待するか、別のグループを招待することができます。"
|
||||
- "Podes convidar um novo para <strong>%{project_name}</strong> ou convidar outro grupo."
|
||||
- "邀请新成员或另一个群组加入<strong>%{project_name}</strong>。"
|
||||
- "Puede invitar a un nuevo miembro a <strong>%{project_name}</strong> o invitar a otro grupo."
|
||||
- "<strong>%{project_name}</strong> projesine yeni bir üye davet edebilir veya başka bir grubu davet edebilirsiniz."
|
||||
- "Вы можете пригласить нового участника в <strong>%{project_name}</strong> или пригласить другую группу."
|
||||
- "Ви можете запросити нового учасника до <strong>%{project_name}</strong> або запросити іншу групу."
|
||||
"You can invite a new member to <strong>%{project_name}</strong>.":
|
||||
plural_id:
|
||||
translations:
|
||||
- "新しいメンバーを<strong>%{project_name} </strong>に招待できます。"
|
||||
- "Podes convidar um novo membro para <strong>%{project_name}</strong>."
|
||||
- "邀请新成员加入<strong>%{project_name}</strong>。"
|
||||
- "Puedes invitar a un nuevo miembro a <strong>%{project_name}</strong>."
|
||||
- "<strong>%{project_name}</strong> projesine yeni bir üye davet edebilirsiniz."
|
||||
- "Вы можете пригласить нового участника в <strong>%{project_name}</strong>."
|
||||
- "Ви можете запросити нового учасника до <strong>%{project_name}</strong>."
|
||||
"You can invite another group to <strong>%{project_name}</strong>.":
|
||||
plural_id:
|
||||
translations:
|
||||
- "他のグループを<strong>%{project_name} </strong>に招待できます。"
|
||||
- "Podes convidar outro grupo para <strong>%{project_name}</strong>."
|
||||
- "您可以邀请另一个群组加入<strong>%{project_name}</strong>。"
|
||||
- "Ви можете запросити нову групу до <strong>%{project_name}</strong>."
|
||||
- "Puedes invitar a otro grupo a <strong>%{project_name}</strong>."
|
||||
"Example: <code>192.168.0.0/24</code>. %{read_more_link}.":
|
||||
plural_id:
|
||||
translations:
|
||||
"Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\\\"%{pg_version_upcoming_url}\\\">the related epic</a> for details.":
|
||||
plural_id:
|
||||
translations:
|
||||
"Authorize <strong>%{user}</strong> to use your account?":
|
||||
plural_id:
|
||||
translations:
|
||||
"DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}.":
|
||||
plural_id:
|
||||
translations:
|
||||
"<project name>":
|
||||
translations:
|
||||
- "<название проекта>"
|
||||
- "<project name>"
|
||||
- "<proje adı>"
|
||||
- "<naziv projekta>"
|
||||
- "<ім’я проєкту>"
|
||||
- "<프로젝트 이름>"
|
||||
|
|
|
@ -47,7 +47,7 @@ module Gitlab
|
|||
|
||||
# We need to remove any newlines since our UrlBlocker does not allow
|
||||
# multiline URLs.
|
||||
query.squish
|
||||
query.to_s.squish
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,20 +8,18 @@ module Gitlab
|
|||
|
||||
class << self
|
||||
def validate(content, schema_path = DASHBOARD_SCHEMA_PATH, dashboard_path: nil, project: nil)
|
||||
errors = _validate(content, schema_path, dashboard_path: dashboard_path, project: project)
|
||||
errors.empty?
|
||||
errors(content, schema_path, dashboard_path: dashboard_path, project: project).empty?
|
||||
end
|
||||
|
||||
def validate!(content, schema_path = DASHBOARD_SCHEMA_PATH, dashboard_path: nil, project: nil)
|
||||
errors = _validate(content, schema_path, dashboard_path: dashboard_path, project: project)
|
||||
errors = errors(content, schema_path, dashboard_path: dashboard_path, project: project)
|
||||
errors.empty? || raise(errors.first)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def _validate(content, schema_path, dashboard_path: nil, project: nil)
|
||||
client = Validator::Client.new(content, schema_path, dashboard_path: dashboard_path, project: project)
|
||||
client.execute
|
||||
def errors(content, schema_path = DASHBOARD_SCHEMA_PATH, dashboard_path: nil, project: nil)
|
||||
Validator::Client
|
||||
.new(content, schema_path, dashboard_path: dashboard_path, project: project)
|
||||
.execute
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -46,7 +46,7 @@ module Gitlab
|
|||
|
||||
def validate_against_schema
|
||||
schemer.validate(content).map do |error|
|
||||
Errors::SchemaValidationError.new(error)
|
||||
::Gitlab::Metrics::Dashboard::Validator::Errors::SchemaValidationError.new(error)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
},
|
||||
"unit": { "type": "string" },
|
||||
"label": { "type": "string" },
|
||||
"query": { "type": "string" },
|
||||
"query_range": { "type": "string" },
|
||||
"query": { "type": ["string", "number"] },
|
||||
"query_range": { "type": ["string", "number"] },
|
||||
"step": { "type": "number" }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": ["area-chart", "anomaly-chart", "bar", "column", "stacked-column", "single-stat", "heatmap"],
|
||||
"enum": ["area-chart", "line-chart", "anomaly-chart", "bar", "column", "stacked-column", "single-stat", "heatmap", "gauge"],
|
||||
"default": "area-chart"
|
||||
},
|
||||
"title": { "type": "string" },
|
||||
|
|
|
@ -697,6 +697,9 @@ msgstr ""
|
|||
msgid "%{state} epics"
|
||||
msgstr ""
|
||||
|
||||
msgid "%{strongStart}Deletes%{strongEnd} source branch"
|
||||
msgstr ""
|
||||
|
||||
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
|
||||
msgstr ""
|
||||
|
||||
|
@ -1075,9 +1078,6 @@ msgstr ""
|
|||
msgid "< 1 hour"
|
||||
msgstr ""
|
||||
|
||||
msgid "<strong>Deletes</strong> source branch"
|
||||
msgstr ""
|
||||
|
||||
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
|
||||
msgstr ""
|
||||
|
||||
|
@ -3761,7 +3761,7 @@ msgstr ""
|
|||
msgid "Badges|This project has no badges"
|
||||
msgstr ""
|
||||
|
||||
msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
|
||||
msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
|
||||
msgstr ""
|
||||
|
||||
msgid "Badges|Your badges"
|
||||
|
@ -5117,9 +5117,6 @@ msgstr ""
|
|||
msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
|
||||
msgstr ""
|
||||
|
||||
|
@ -5174,6 +5171,9 @@ msgstr ""
|
|||
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterIntegration|All installed applications and related resources"
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
|
||||
msgstr ""
|
||||
|
||||
|
@ -5198,6 +5198,9 @@ msgstr ""
|
|||
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterIntegration|Any project namespaces"
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterIntegration|Any running pipelines will be canceled."
|
||||
msgstr ""
|
||||
|
||||
|
@ -5870,6 +5873,9 @@ msgstr ""
|
|||
msgid "ClusterIntegration|Subnets"
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
|
||||
msgstr ""
|
||||
|
||||
|
@ -5909,15 +5915,27 @@ msgstr ""
|
|||
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterIntegration|This will permanently delete the following resources:"
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterIntegration|Uninstall %{appTitle}"
|
||||
msgstr ""
|
||||
|
||||
|
@ -5942,6 +5960,9 @@ msgstr ""
|
|||
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
|
||||
msgstr ""
|
||||
|
||||
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
|
||||
msgstr ""
|
||||
|
||||
|
@ -6373,7 +6394,7 @@ msgstr ""
|
|||
msgid "Configure Tracing"
|
||||
msgstr ""
|
||||
|
||||
msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
|
||||
msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Configure automatic git checks and housekeeping on repositories."
|
||||
|
@ -7429,6 +7450,15 @@ msgstr ""
|
|||
msgid "Customize your pipeline configuration."
|
||||
msgstr ""
|
||||
|
||||
msgid "CustomizeHomepageBanner|Do you want to customize this page?"
|
||||
msgstr ""
|
||||
|
||||
msgid "CustomizeHomepageBanner|Go to preferences"
|
||||
msgstr ""
|
||||
|
||||
msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
|
||||
msgstr ""
|
||||
|
||||
msgid "Cycle Time"
|
||||
msgstr ""
|
||||
|
||||
|
@ -8069,8 +8099,8 @@ msgid_plural "Depends on %d merge requests being merged"
|
|||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "Depends on <strong>%d closed</strong> merge request."
|
||||
msgid_plural "Depends on <strong>%d closed</strong> merge requests."
|
||||
msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
|
||||
msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
|
@ -11644,7 +11674,7 @@ msgstr ""
|
|||
msgid "Go to %{link_to_google_takeout}."
|
||||
msgstr ""
|
||||
|
||||
msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
|
||||
msgid "Go to %{strongStart}Issues%{strongEnd} > %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
|
||||
msgstr ""
|
||||
|
||||
msgid "Go to Webhooks"
|
||||
|
@ -13948,7 +13978,7 @@ msgstr ""
|
|||
msgid "Labels can be applied to issues and merge requests."
|
||||
msgstr ""
|
||||
|
||||
msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
|
||||
msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Labels|Promote Label"
|
||||
|
@ -14516,7 +14546,7 @@ msgstr ""
|
|||
msgid "Lock the discussion"
|
||||
msgstr ""
|
||||
|
||||
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
|
||||
msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
|
||||
msgstr ""
|
||||
|
||||
msgid "Lock to current projects"
|
||||
|
@ -19534,9 +19564,6 @@ msgstr ""
|
|||
msgid "PrometheusService|%{exporters} with %{metrics} were found"
|
||||
msgstr ""
|
||||
|
||||
msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
|
||||
msgstr ""
|
||||
|
||||
msgid "PrometheusService|Active"
|
||||
msgstr ""
|
||||
|
||||
|
@ -19594,6 +19621,9 @@ msgstr ""
|
|||
msgid "PrometheusService|New metric"
|
||||
msgstr ""
|
||||
|
||||
msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
|
||||
msgstr ""
|
||||
|
||||
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
|
||||
msgstr ""
|
||||
|
||||
|
@ -25193,9 +25223,6 @@ msgstr ""
|
|||
msgid "This project does not have a wiki homepage yet"
|
||||
msgstr ""
|
||||
|
||||
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
|
||||
msgstr ""
|
||||
|
||||
msgid "This project has no active access tokens."
|
||||
msgstr ""
|
||||
|
||||
|
@ -26229,7 +26256,7 @@ msgstr ""
|
|||
msgid "Unlock the discussion"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
|
||||
msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
|
||||
msgstr ""
|
||||
|
||||
msgid "Unlocked"
|
||||
|
@ -27849,10 +27876,10 @@ msgstr ""
|
|||
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
|
||||
msgstr ""
|
||||
|
||||
msgid "You are going to turn off the confidentiality. This means %{accessLevel} will be able to see and leave a comment on this %{issuableType}."
|
||||
msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
|
||||
msgstr ""
|
||||
|
||||
msgid "You are going to turn on the confidentiality. This means that only team members with %{accessLevel} are able to see and leave comments on the %{issuableType}."
|
||||
msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
|
||||
msgstr ""
|
||||
|
||||
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
|
||||
|
@ -28580,9 +28607,6 @@ msgstr ""
|
|||
msgid "assign yourself"
|
||||
msgstr ""
|
||||
|
||||
msgid "at least Reporter access"
|
||||
msgstr ""
|
||||
|
||||
msgid "at risk"
|
||||
msgstr ""
|
||||
|
||||
|
@ -28973,9 +28997,6 @@ msgstr ""
|
|||
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
|
||||
msgstr ""
|
||||
|
||||
msgid "everyone"
|
||||
msgstr ""
|
||||
|
||||
msgid "exceeds the limit of %{bytes} bytes"
|
||||
msgstr ""
|
||||
|
||||
|
@ -29940,6 +29961,9 @@ msgstr ""
|
|||
msgid "vulnerability|Add comment & dismiss"
|
||||
msgstr ""
|
||||
|
||||
msgid "vulnerability|Add comment and dismiss"
|
||||
msgstr ""
|
||||
|
||||
msgid "vulnerability|Dismiss vulnerability"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -122,6 +122,30 @@ RSpec.describe RootController do
|
|||
|
||||
expect(response).to render_template 'dashboard/projects/index'
|
||||
end
|
||||
|
||||
context 'when experiment is enabled' do
|
||||
before do
|
||||
stub_experiment_for_user(customize_homepage: true)
|
||||
end
|
||||
|
||||
it 'renders the default dashboard' do
|
||||
get :index
|
||||
|
||||
expect(assigns[:customize_homepage]).to be true
|
||||
end
|
||||
end
|
||||
|
||||
context 'when experiment not enabled' do
|
||||
before do
|
||||
stub_experiment(customize_homepage: false)
|
||||
end
|
||||
|
||||
it 'renders the default dashboard' do
|
||||
get :index
|
||||
|
||||
expect(assigns[:customize_homepage]).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -95,20 +95,32 @@ RSpec.describe 'Merge request > User posts notes', :js do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'reply on a deleted conversation' do
|
||||
before do
|
||||
visit project_merge_request_path(project, merge_request)
|
||||
end
|
||||
|
||||
it 'shows an error message' do
|
||||
describe 'replying to a comment' do
|
||||
it 'makes the discussion resolvable' do
|
||||
find('.js-reply-button').click
|
||||
note.delete
|
||||
|
||||
page.within('.discussion-reply-holder') do
|
||||
fill_in 'note[note]', with: 'A reply'
|
||||
click_button 'Add comment now'
|
||||
wait_for_requests
|
||||
expect(page).to have_content('Your comment could not be submitted because discussion to reply to cannot be found')
|
||||
|
||||
expect(page).to have_button('Resolve thread')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when comment is deleted' do
|
||||
before do
|
||||
note.delete
|
||||
end
|
||||
|
||||
it 'shows an error message' do
|
||||
find('.js-reply-button').click
|
||||
|
||||
page.within('.discussion-reply-holder') do
|
||||
fill_in 'note[note]', with: 'A reply'
|
||||
click_button 'Add comment now'
|
||||
|
||||
expect(page).to have_content('Your comment could not be submitted because discussion to reply to cannot be found')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -589,7 +589,7 @@ RSpec.describe 'File blob', :js do
|
|||
aggregate_failures do
|
||||
# shows that dashboard yaml is invalid
|
||||
expect(page).to have_content('Metrics Dashboard YAML definition is invalid:')
|
||||
expect(page).to have_content("panel_groups: should be an array of panel_groups objects")
|
||||
expect(page).to have_content("root is missing required keys: panel_groups")
|
||||
|
||||
# shows a learn more link
|
||||
expect(page).to have_link('Learn more')
|
||||
|
|
|
@ -48,7 +48,7 @@ panel_groups:
|
|||
y_label: "y_label"
|
||||
metrics:
|
||||
- id: metric_a2
|
||||
query_range: 'query'
|
||||
query_range: 2000
|
||||
label: Legend Label
|
||||
unit: unit
|
||||
- title: "Super Chart A1"
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
],
|
||||
"properties": {
|
||||
"id": { "type": "string" },
|
||||
"query_range": { "type": "string" },
|
||||
"query": { "type": "string" },
|
||||
"query_range": { "type": ["string", "number"] },
|
||||
"query": { "type": ["string", "number"] },
|
||||
"unit": { "type": "string" },
|
||||
"label": { "type": "string" },
|
||||
"track": { "type": "string" },
|
||||
|
|
|
@ -15,6 +15,8 @@ describe('IDE store terminal messages', () => {
|
|||
sprintf(
|
||||
messages.ERROR_CONFIG,
|
||||
{
|
||||
codeStart: `<code>`,
|
||||
codeEnd: `</code>`,
|
||||
helpStart: `<a href="${escape(TEST_HELP_URL)}" target="_blank">`,
|
||||
helpEnd: '</a>',
|
||||
},
|
||||
|
|
|
@ -2,7 +2,7 @@ import { shallowMount, mount } from '@vue/test-utils';
|
|||
import VueDraggable from 'vuedraggable';
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
import { TEST_HOST } from 'helpers/test_constants';
|
||||
import { ESC_KEY, ESC_KEY_IE11 } from '~/lib/utils/keys';
|
||||
import { ESC_KEY } from '~/lib/utils/keys';
|
||||
import { objectToQuery } from '~/lib/utils/url_utility';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import { dashboardEmptyStates, metricStates } from '~/monitoring/constants';
|
||||
|
@ -566,15 +566,6 @@ describe('Dashboard', () => {
|
|||
undefined,
|
||||
);
|
||||
});
|
||||
|
||||
it('restores dashboard from full screen by typing the Escape key on IE11', () => {
|
||||
mockKeyup(ESC_KEY_IE11);
|
||||
|
||||
expect(store.dispatch).toHaveBeenCalledWith(
|
||||
`monitoringDashboard/clearExpandedPanel`,
|
||||
undefined,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import CustomizeHomepageBanner from '~/pages/dashboard/projects/index/components/customize_homepage_banner.vue';
|
||||
import { GlBanner } from '@gitlab/ui';
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
|
||||
const svgPath = '/illustrations/background';
|
||||
const provide = {
|
||||
svgPath,
|
||||
preferencesBehaviorPath: 'some/behavior/path',
|
||||
calloutsPath: 'call/out/path',
|
||||
calloutsFeatureId: 'some-feature-id',
|
||||
};
|
||||
|
||||
const createComponent = () => {
|
||||
return shallowMount(CustomizeHomepageBanner, { provide });
|
||||
};
|
||||
|
||||
describe('CustomizeHomepageBanner', () => {
|
||||
let mockAxios;
|
||||
let wrapper;
|
||||
|
||||
beforeEach(() => {
|
||||
mockAxios = new MockAdapter(axios);
|
||||
wrapper = createComponent();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
wrapper = null;
|
||||
mockAxios.restore();
|
||||
});
|
||||
|
||||
it('should render the banner when not dismissed', () => {
|
||||
expect(wrapper.contains(GlBanner)).toBe(true);
|
||||
});
|
||||
|
||||
it('should close the banner when dismiss is clicked', async () => {
|
||||
mockAxios.onPost(provide.calloutsPath).replyOnce(200);
|
||||
expect(wrapper.contains(GlBanner)).toBe(true);
|
||||
wrapper.find(GlBanner).vm.$emit('close');
|
||||
|
||||
await wrapper.vm.$nextTick();
|
||||
expect(wrapper.contains(GlBanner)).toBe(false);
|
||||
});
|
||||
|
||||
it('includes the body text from options', () => {
|
||||
expect(wrapper.html()).toContain(wrapper.vm.$options.i18n.body);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,50 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Edit Form Dropdown when confidential renders on or off text based on confidentiality 1`] = `
|
||||
<div
|
||||
class="dropdown show"
|
||||
toggleform="function () {}"
|
||||
updateconfidentialattribute="function () {}"
|
||||
>
|
||||
<div
|
||||
class="dropdown-menu sidebar-item-warning-message"
|
||||
>
|
||||
<div>
|
||||
<p>
|
||||
<gl-sprintf-stub
|
||||
message="You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
|
||||
/>
|
||||
</p>
|
||||
|
||||
<edit-form-buttons-stub
|
||||
confidential="true"
|
||||
fullpath=""
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Edit Form Dropdown when not confidential renders "You are going to turn on the confidentiality." in the 1`] = `
|
||||
<div
|
||||
class="dropdown show"
|
||||
toggleform="function () {}"
|
||||
updateconfidentialattribute="function () {}"
|
||||
>
|
||||
<div
|
||||
class="dropdown-menu sidebar-item-warning-message"
|
||||
>
|
||||
<div>
|
||||
<p>
|
||||
<gl-sprintf-stub
|
||||
message="You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
|
||||
/>
|
||||
</p>
|
||||
|
||||
<edit-form-buttons-stub
|
||||
fullpath=""
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
|
@ -23,14 +23,14 @@ describe('Edit Form Dropdown', () => {
|
|||
});
|
||||
|
||||
describe('when not confidential', () => {
|
||||
it('renders "You are going to turn off the confidentiality." in the ', () => {
|
||||
it('renders "You are going to turn on the confidentiality." in the ', () => {
|
||||
createComponent({
|
||||
confidential: false,
|
||||
toggleForm,
|
||||
updateConfidentialAttribute,
|
||||
});
|
||||
|
||||
expect(wrapper.find('p').text()).toContain('You are going to turn on the confidentiality.');
|
||||
expect(wrapper.element).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -42,7 +42,7 @@ describe('Edit Form Dropdown', () => {
|
|||
updateConfidentialAttribute,
|
||||
});
|
||||
|
||||
expect(wrapper.find('p').text()).toContain('You are going to turn off the confidentiality.');
|
||||
expect(wrapper.element).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Edit Form Dropdown In issue page when locked the appropriate warning text is rendered 1`] = `
|
||||
<div
|
||||
class="dropdown-menu sidebar-item-warning-message"
|
||||
data-testid="warning-text"
|
||||
>
|
||||
<p
|
||||
class="text"
|
||||
>
|
||||
<gl-sprintf-stub
|
||||
message="Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
|
||||
/>
|
||||
</p>
|
||||
|
||||
<edit-form-buttons-stub
|
||||
islocked="true"
|
||||
issuabledisplayname="issue"
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Edit Form Dropdown In issue page when unlocked the appropriate warning text is rendered 1`] = `
|
||||
<div
|
||||
class="dropdown-menu sidebar-item-warning-message"
|
||||
data-testid="warning-text"
|
||||
>
|
||||
<p
|
||||
class="text"
|
||||
>
|
||||
<gl-sprintf-stub
|
||||
message="Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
|
||||
/>
|
||||
</p>
|
||||
|
||||
<edit-form-buttons-stub
|
||||
issuabledisplayname="issue"
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Edit Form Dropdown In merge request page when locked the appropriate warning text is rendered 1`] = `
|
||||
<div
|
||||
class="dropdown-menu sidebar-item-warning-message"
|
||||
data-testid="warning-text"
|
||||
>
|
||||
<p
|
||||
class="text"
|
||||
>
|
||||
<gl-sprintf-stub
|
||||
message="Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
|
||||
/>
|
||||
</p>
|
||||
|
||||
<edit-form-buttons-stub
|
||||
islocked="true"
|
||||
issuabledisplayname="merge request"
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Edit Form Dropdown In merge request page when unlocked the appropriate warning text is rendered 1`] = `
|
||||
<div
|
||||
class="dropdown-menu sidebar-item-warning-message"
|
||||
data-testid="warning-text"
|
||||
>
|
||||
<p
|
||||
class="text"
|
||||
>
|
||||
<gl-sprintf-stub
|
||||
message="Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
|
||||
/>
|
||||
</p>
|
||||
|
||||
<edit-form-buttons-stub
|
||||
issuabledisplayname="merge request"
|
||||
/>
|
||||
</div>
|
||||
`;
|
|
@ -38,18 +38,16 @@ describe('Edit Form Dropdown', () => {
|
|||
});
|
||||
|
||||
describe.each`
|
||||
isLocked | lockStatusText | lockAction | warningText
|
||||
${false} | ${'unlocked'} | ${'Lock'} | ${'Only project members will be able to comment.'}
|
||||
${true} | ${'locked'} | ${'Unlock'} | ${'Everyone will be able to comment.'}
|
||||
`('when $lockStatusText', ({ isLocked, lockAction, warningText }) => {
|
||||
isLocked | lockStatusText
|
||||
${false} | ${'unlocked'}
|
||||
${true} | ${'locked'}
|
||||
`('when $lockStatusText', ({ isLocked }) => {
|
||||
beforeEach(() => {
|
||||
createComponent({ props: { isLocked } });
|
||||
});
|
||||
|
||||
it(`the appropriate warning text is rendered`, () => {
|
||||
expect(findWarningText().text()).toContain(
|
||||
`${lockAction} this ${issuableDisplayName}? ${warningText}`,
|
||||
);
|
||||
expect(findWarningText().element).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Types::UserStatusType do
|
||||
specify { expect(described_class.graphql_name).to eq('UserStatus') }
|
||||
|
||||
it 'exposes the expected fields' do
|
||||
expected_fields = %i[
|
||||
emoji
|
||||
message
|
||||
message_html
|
||||
]
|
||||
|
||||
expect(described_class).to have_graphql_fields(*expected_fields)
|
||||
end
|
||||
end
|
|
@ -14,11 +14,13 @@ RSpec.describe GitlabSchema.types['User'] do
|
|||
snippets
|
||||
name
|
||||
username
|
||||
email
|
||||
avatarUrl
|
||||
webUrl
|
||||
webPath
|
||||
todos
|
||||
state
|
||||
status
|
||||
authoredMergeRequests
|
||||
assignedMergeRequests
|
||||
groupMemberships
|
||||
|
|
|
@ -81,6 +81,36 @@ RSpec.describe UserCalloutsHelper do
|
|||
end
|
||||
end
|
||||
|
||||
describe '.show_customize_homepage_banner?' do
|
||||
let(:customize_homepage) { true }
|
||||
|
||||
subject { helper.show_customize_homepage_banner?(customize_homepage) }
|
||||
|
||||
context 'when user has not dismissed' do
|
||||
before do
|
||||
allow(helper).to receive(:user_dismissed?).with(described_class::CUSTOMIZE_HOMEPAGE) { false }
|
||||
end
|
||||
|
||||
context 'when customize_homepage is set' do
|
||||
it { is_expected.to be true }
|
||||
end
|
||||
|
||||
context 'when customize_homepage is false' do
|
||||
let(:customize_homepage) { false }
|
||||
|
||||
it { is_expected.to be false }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user dismissed' do
|
||||
before do
|
||||
allow(helper).to receive(:user_dismissed?).with(described_class::CUSTOMIZE_HOMEPAGE) { true }
|
||||
end
|
||||
|
||||
it { is_expected.to be false }
|
||||
end
|
||||
end
|
||||
|
||||
describe '.render_flash_user_callout' do
|
||||
it 'renders the flash_user_callout partial' do
|
||||
expect(helper).to receive(:render)
|
||||
|
|
|
@ -27,9 +27,17 @@ RSpec.describe Gitlab::Metrics::Dashboard::Stages::MetricEndpointInserter do
|
|||
transform!
|
||||
|
||||
expect(all_metrics).to satisfy_all do |metric|
|
||||
metric[:prometheus_endpoint_path] == prometheus_path(metric[:query_range].squish)
|
||||
metric[:prometheus_endpoint_path].present? && !metric[:prometheus_endpoint_path].include?("\n")
|
||||
end
|
||||
end
|
||||
|
||||
it 'works when query/query_range is a number' do
|
||||
query = 2000
|
||||
|
||||
transform!
|
||||
|
||||
expect(all_metrics[1][:prometheus_endpoint_path]).to eq(prometheus_path(query))
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -34,6 +34,19 @@ RSpec.describe Gitlab::Metrics::Dashboard::Validator::Errors do
|
|||
|
||||
it { is_expected.to eq 'root is missing required keys: one' }
|
||||
end
|
||||
|
||||
context 'when there is type mismatch' do
|
||||
%w(null string boolean integer number array object).each do |expected_type|
|
||||
context "on type: #{expected_type}" do
|
||||
let(:type) { expected_type }
|
||||
let(:details) { nil }
|
||||
|
||||
subject { described_class.new(error_hash).message }
|
||||
|
||||
it { is_expected.to eq "'property_name' at root is not of type: #{expected_type}" }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'for nested object' do
|
||||
|
|
|
@ -143,4 +143,56 @@ RSpec.describe Gitlab::Metrics::Dashboard::Validator do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#errors' do
|
||||
context 'valid dashboard schema' do
|
||||
it 'returns no errors' do
|
||||
expect(described_class.errors(valid_dashboard)).to eq []
|
||||
end
|
||||
|
||||
context 'with duplicate metric_ids' do
|
||||
it 'returns errors' do
|
||||
expect(described_class.errors(duplicate_id_dashboard)).to eq [Gitlab::Metrics::Dashboard::Validator::Errors::DuplicateMetricIds.new]
|
||||
end
|
||||
end
|
||||
|
||||
context 'with dashboard_path and project' do
|
||||
subject { described_class.errors(valid_dashboard, dashboard_path: 'test/path.yml', project: project) }
|
||||
|
||||
context 'with no conflicting metric identifiers in db' do
|
||||
it { is_expected.to eq [] }
|
||||
end
|
||||
|
||||
context 'with metric identifier present in current dashboard' do
|
||||
before do
|
||||
create(:prometheus_metric,
|
||||
identifier: 'metric_a1',
|
||||
dashboard_path: 'test/path.yml',
|
||||
project: project
|
||||
)
|
||||
end
|
||||
|
||||
it { is_expected.to eq [] }
|
||||
end
|
||||
|
||||
context 'with metric identifier present in another dashboard' do
|
||||
before do
|
||||
create(:prometheus_metric,
|
||||
identifier: 'metric_a1',
|
||||
dashboard_path: 'some/other/dashboard/path.yml',
|
||||
project: project
|
||||
)
|
||||
end
|
||||
|
||||
it { is_expected.to eq [Gitlab::Metrics::Dashboard::Validator::Errors::DuplicateMetricIds.new] }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'invalid dashboard schema' do
|
||||
it 'returns collection of validation errors' do
|
||||
expect(described_class.errors(invalid_dashboard)).to all be_kind_of(Gitlab::Metrics::Dashboard::Validator::Errors::SchemaValidationError)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
# frozen_string_literal: true
|
||||
require 'spec_helper'
|
||||
require Rails.root.join('db', 'post_migrate', '20200811130433_create_missing_vulnerabilities_issue_links.rb')
|
||||
|
||||
RSpec.describe CreateMissingVulnerabilitiesIssueLinks, :migration do
|
||||
let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
|
||||
let(:users) { table(:users) }
|
||||
let(:user) { create_user! }
|
||||
let(:project) { table(:projects).create!(id: 123, namespace_id: namespace.id) }
|
||||
let(:scanner) { table(:vulnerability_scanners).create!(project_id: project.id, external_id: 'test', name: 'test scanner') }
|
||||
let(:issue) { table(:issues).create!(id: 123, project_id: project.id) }
|
||||
let(:vulnerabilities) { table(:vulnerabilities) }
|
||||
let(:vulnerabilities_findings) { table(:vulnerability_occurrences) }
|
||||
let(:vulnerability_feedback) { table(:vulnerability_feedback) }
|
||||
let(:vulnerability_issue_links) { table(:vulnerability_issue_links) }
|
||||
let(:vulnerability_identifier) { table(:vulnerability_identifiers).create!(project_id: project.id, external_type: 'test', external_id: 'test', fingerprint: 'test', name: 'test') }
|
||||
|
||||
let!(:vulnerability) do
|
||||
create_vulnerability!(
|
||||
project_id: project.id,
|
||||
author_id: user.id
|
||||
)
|
||||
end
|
||||
|
||||
before do
|
||||
create_finding!(
|
||||
vulnerability_id: vulnerability.id,
|
||||
project_id: project.id,
|
||||
scanner_id: scanner.id,
|
||||
primary_identifier_id: vulnerability_identifier.id
|
||||
)
|
||||
create_feedback!(
|
||||
issue_id: issue.id,
|
||||
project_id: project.id,
|
||||
author_id: user.id
|
||||
)
|
||||
end
|
||||
|
||||
context 'with no Vulnerabilities::IssueLinks present' do
|
||||
it 'creates missing Vulnerabilities::IssueLinks' do
|
||||
expect(vulnerability_issue_links.count).to eq(0)
|
||||
|
||||
migrate!
|
||||
|
||||
expect(vulnerability_issue_links.count).to eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when an Vulnerabilities::IssueLink already exists' do
|
||||
before do
|
||||
vulnerability_issue_links.create!(vulnerability_id: vulnerability.id, issue_id: issue.id)
|
||||
end
|
||||
|
||||
it 'creates no duplicates' do
|
||||
expect(vulnerability_issue_links.count).to eq(1)
|
||||
|
||||
migrate!
|
||||
|
||||
expect(vulnerability_issue_links.count).to eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_vulnerability!(project_id:, author_id:, title: 'test', severity: 7, confidence: 7, report_type: 0)
|
||||
vulnerabilities.create!(
|
||||
project_id: project_id,
|
||||
author_id: author_id,
|
||||
title: title,
|
||||
severity: severity,
|
||||
confidence: confidence,
|
||||
report_type: report_type
|
||||
)
|
||||
end
|
||||
|
||||
# rubocop:disable Metrics/ParameterLists
|
||||
def create_finding!(
|
||||
vulnerability_id:, project_id:, scanner_id:, primary_identifier_id:,
|
||||
name: "test", severity: 7, confidence: 7, report_type: 0,
|
||||
project_fingerprint: '123qweasdzxc', location_fingerprint: 'test',
|
||||
metadata_version: 'test', raw_metadata: 'test', uuid: 'test')
|
||||
vulnerabilities_findings.create!(
|
||||
vulnerability_id: vulnerability_id,
|
||||
project_id: project_id,
|
||||
name: name,
|
||||
severity: severity,
|
||||
confidence: confidence,
|
||||
report_type: report_type,
|
||||
project_fingerprint: project_fingerprint,
|
||||
scanner_id: scanner.id,
|
||||
primary_identifier_id: vulnerability_identifier.id,
|
||||
location_fingerprint: location_fingerprint,
|
||||
metadata_version: metadata_version,
|
||||
raw_metadata: raw_metadata,
|
||||
uuid: uuid
|
||||
)
|
||||
end
|
||||
# rubocop:enable Metrics/ParameterLists
|
||||
|
||||
# project_fingerprint on Vulnerabilities::Finding is a bytea and we need to match this
|
||||
def create_feedback!(issue_id:, project_id:, author_id:, feedback_type: 1, category: 0, project_fingerprint: '3132337177656173647a7863')
|
||||
vulnerability_feedback.create!(
|
||||
feedback_type: feedback_type,
|
||||
issue_id: issue.id,
|
||||
category: category,
|
||||
project_fingerprint: project_fingerprint,
|
||||
project_id: project_id,
|
||||
author_id: author_id
|
||||
)
|
||||
end
|
||||
|
||||
def create_user!(name: "Example User", email: "user@example.com", user_type: nil, created_at: Time.now, confirmed_at: Time.now)
|
||||
users.create!(
|
||||
name: name,
|
||||
email: email,
|
||||
username: name,
|
||||
projects_limit: 0,
|
||||
user_type: user_type,
|
||||
confirmed_at: confirmed_at
|
||||
)
|
||||
end
|
||||
end
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue