Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
669f67690a
commit
1063cd719c
49 changed files with 1962 additions and 330 deletions
|
@ -1 +1 @@
|
|||
dfdc9b7725eb710dab8ae9970e98cc5118e65c49
|
||||
092d4e489d7de1dcc38d57a4c667e85df8b8377f
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import { GlTable, GlIcon, GlTooltipDirective } from '@gitlab/ui';
|
||||
import { s__, __ } from '~/locale';
|
||||
import Tracking from '~/tracking';
|
||||
import { trackAlertIntergrationsViewsOptions } from '../constants';
|
||||
import { trackAlertIntegrationsViewsOptions } from '../constants';
|
||||
|
||||
export const i18n = {
|
||||
title: s__('AlertsIntegrations|Current integrations'),
|
||||
|
@ -64,7 +64,7 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
trackPageViews() {
|
||||
const { category, action } = trackAlertIntergrationsViewsOptions;
|
||||
const { category, action } = trackAlertIntegrationsViewsOptions;
|
||||
Tracking.event(category, action);
|
||||
},
|
||||
},
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
<script>
|
||||
import {
|
||||
GlButton,
|
||||
GlCollapse,
|
||||
GlForm,
|
||||
GlFormGroup,
|
||||
GlFormSelect,
|
||||
GlFormInput,
|
||||
GlLink,
|
||||
GlSprintf,
|
||||
} from '@gitlab/ui';
|
||||
import { s__ } from '~/locale';
|
||||
import { integrationTypes } from '../constants';
|
||||
|
||||
export default {
|
||||
i18n: {
|
||||
integrationsInfo: s__(
|
||||
'AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}',
|
||||
),
|
||||
integrationFormSteps: {
|
||||
step1: s__('AlertSettings|1. Select integration type'),
|
||||
step2: s__('AlertSettings|2. Name integration'),
|
||||
},
|
||||
},
|
||||
components: {
|
||||
GlButton,
|
||||
GlCollapse,
|
||||
GlForm,
|
||||
GlFormGroup,
|
||||
GlFormInput,
|
||||
GlFormSelect,
|
||||
GlLink,
|
||||
GlSprintf,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedIntegration: integrationTypes[0].value,
|
||||
options: integrationTypes,
|
||||
formVisible: false,
|
||||
form: {
|
||||
name: '',
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onIntegrationTypeSelect() {
|
||||
if (this.selectedIntegration === integrationTypes[0].value) {
|
||||
this.formVisible = false;
|
||||
} else {
|
||||
this.formVisible = true;
|
||||
}
|
||||
},
|
||||
onSubmit() {
|
||||
// TODO Add GraphQL method
|
||||
},
|
||||
onReset() {
|
||||
this.form.name = '';
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<gl-form class="gl-mt-6" @submit.prevent="onSubmit" @reset.prevent="onReset">
|
||||
<h5 class="gl-font-lg gl-my-5">{{ s__('AlertSettings|Add new integrations') }}</h5>
|
||||
|
||||
<gl-form-group
|
||||
id="integration-type"
|
||||
:label="$options.i18n.integrationFormSteps.step1"
|
||||
label-for="integration-type"
|
||||
>
|
||||
<gl-form-select
|
||||
id="integration-type"
|
||||
v-model="selectedIntegration"
|
||||
:options="options"
|
||||
@change="onIntegrationTypeSelect"
|
||||
/>
|
||||
<span class="gl-text-gray-500">
|
||||
<gl-sprintf :message="$options.i18n.integrationsInfo">
|
||||
<template #link="{ content }">
|
||||
<gl-link
|
||||
class="gl-display-inline-block"
|
||||
href="https://gitlab.com/groups/gitlab-org/-/epics/4390"
|
||||
target="_blank"
|
||||
>{{ content }}</gl-link
|
||||
>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</span>
|
||||
</gl-form-group>
|
||||
<gl-collapse v-model="formVisible" class="gl-mt-3">
|
||||
<gl-form-group
|
||||
id="name-integration"
|
||||
:label="$options.i18n.integrationFormSteps.step2"
|
||||
label-for="name-integration"
|
||||
>
|
||||
<gl-form-input
|
||||
id="name-integration"
|
||||
v-model="form.name"
|
||||
type="text"
|
||||
:placeholder="s__('AlertSettings|Enter integration name')"
|
||||
/>
|
||||
</gl-form-group>
|
||||
<div class="gl-display-flex gl-justify-content-end">
|
||||
<gl-button type="reset" class="gl-mr-3 js-no-auto-disable">{{ __('Cancel') }}</gl-button>
|
||||
<gl-button
|
||||
type="submit"
|
||||
category="secondary"
|
||||
variant="success"
|
||||
class="gl-mr-1 js-no-auto-disable"
|
||||
>{{ __('Save and test payload') }}</gl-button
|
||||
>
|
||||
<gl-button type="submit" variant="success" class="js-no-auto-disable">{{
|
||||
s__('AlertSettings|Save integration')
|
||||
}}</gl-button>
|
||||
</div>
|
||||
</gl-collapse>
|
||||
</gl-form>
|
||||
</template>
|
|
@ -14,16 +14,14 @@ import {
|
|||
GlFormSelect,
|
||||
} from '@gitlab/ui';
|
||||
import { debounce } from 'lodash';
|
||||
import { s__ } from '~/locale';
|
||||
import { doesHashExistInUrl } from '~/lib/utils/url_utility';
|
||||
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
|
||||
import ToggleButton from '~/vue_shared/components/toggle_button.vue';
|
||||
import IntegrationsList from './alerts_integrations_list.vue';
|
||||
import csrf from '~/lib/utils/csrf';
|
||||
import service from '../services';
|
||||
import {
|
||||
i18n,
|
||||
serviceOptions,
|
||||
integrationTypes,
|
||||
JSON_VALIDATE_DELAY,
|
||||
targetPrometheusUrlPlaceholder,
|
||||
targetOpsgenieUrlPlaceholder,
|
||||
|
@ -50,7 +48,6 @@ export default {
|
|||
GlSprintf,
|
||||
ClipboardButton,
|
||||
ToggleButton,
|
||||
IntegrationsList,
|
||||
},
|
||||
directives: {
|
||||
'gl-modal': GlModalDirective,
|
||||
|
@ -59,8 +56,8 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
selectedEndpoint: serviceOptions[0].value,
|
||||
options: serviceOptions,
|
||||
selectedIntegration: integrationTypes[1].value,
|
||||
options: integrationTypes,
|
||||
active: false,
|
||||
authKey: '',
|
||||
targetUrl: '',
|
||||
|
@ -91,13 +88,13 @@ export default {
|
|||
];
|
||||
},
|
||||
isPrometheus() {
|
||||
return this.selectedEndpoint === 'prometheus';
|
||||
return this.selectedIntegration === 'prometheus';
|
||||
},
|
||||
isOpsgenie() {
|
||||
return this.selectedEndpoint === 'opsgenie';
|
||||
return this.selectedIntegration === 'opsgenie';
|
||||
},
|
||||
selectedService() {
|
||||
switch (this.selectedEndpoint) {
|
||||
selectedIntegrationType() {
|
||||
switch (this.selectedIntegration) {
|
||||
case 'generic': {
|
||||
return {
|
||||
url: this.generic.url,
|
||||
|
@ -152,27 +149,13 @@ export default {
|
|||
? this.$options.targetOpsgenieUrlPlaceholder
|
||||
: this.$options.targetPrometheusUrlPlaceholder;
|
||||
},
|
||||
integrations() {
|
||||
return [
|
||||
{
|
||||
name: s__('AlertSettings|HTTP endpoint'),
|
||||
type: s__('AlertsIntegrations|HTTP endpoint'),
|
||||
activated: this.generic.activated,
|
||||
},
|
||||
{
|
||||
name: s__('AlertSettings|External Prometheus'),
|
||||
type: s__('AlertsIntegrations|Prometheus'),
|
||||
activated: this.prometheus.activated,
|
||||
},
|
||||
];
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
'testAlert.json': debounce(function debouncedJsonValidate() {
|
||||
this.validateJson();
|
||||
}, JSON_VALIDATE_DELAY),
|
||||
targetUrl(oldVal, newVal) {
|
||||
if (newVal && oldVal !== this.selectedService.targetUrl) {
|
||||
if (newVal && oldVal !== this.selectedIntegrationType.targetUrl) {
|
||||
this.canSaveForm = true;
|
||||
}
|
||||
},
|
||||
|
@ -187,8 +170,8 @@ export default {
|
|||
} else if (this.opsgenie.activated) {
|
||||
this.setOpsgenieAsDefault();
|
||||
}
|
||||
this.active = this.selectedService.activated;
|
||||
this.authKey = this.selectedService.authKey ?? '';
|
||||
this.active = this.selectedIntegrationType.activated;
|
||||
this.authKey = this.selectedIntegrationType.authKey ?? '';
|
||||
},
|
||||
methods: {
|
||||
createUserErrorMessage(errors = {}) {
|
||||
|
@ -205,9 +188,9 @@ export default {
|
|||
}
|
||||
return { ...el, disabled: false };
|
||||
});
|
||||
this.selectedEndpoint = this.options.find(({ value }) => value === 'opsgenie').value;
|
||||
this.selectedIntegration = this.options.find(({ value }) => value === 'opsgenie').value;
|
||||
if (this.targetUrl === null) {
|
||||
this.targetUrl = this.selectedService.targetUrl;
|
||||
this.targetUrl = this.selectedIntegrationType.targetUrl;
|
||||
}
|
||||
},
|
||||
removeOpsGenieOption() {
|
||||
|
@ -220,8 +203,8 @@ export default {
|
|||
},
|
||||
resetFormValues() {
|
||||
this.testAlert.json = null;
|
||||
this.targetUrl = this.selectedService.targetUrl;
|
||||
this.active = this.selectedService.activated;
|
||||
this.targetUrl = this.selectedIntegrationType.targetUrl;
|
||||
this.active = this.selectedIntegrationType.activated;
|
||||
},
|
||||
dismissFeedback() {
|
||||
this.serverError = null;
|
||||
|
@ -261,7 +244,7 @@ export default {
|
|||
this.loading = true;
|
||||
return service
|
||||
.updateGenericActive({
|
||||
endpoint: this[this.selectedEndpoint].formPath,
|
||||
endpoint: this[this.selectedIntegration].formPath,
|
||||
params: this.isOpsgenie
|
||||
? { service: { opsgenie_mvc_target_url: this.targetUrl, opsgenie_mvc_enabled: value } }
|
||||
: { service: { active: value } },
|
||||
|
@ -331,9 +314,9 @@ export default {
|
|||
this.validateJson();
|
||||
return service
|
||||
.updateTestAlert({
|
||||
endpoint: this.selectedService.url,
|
||||
endpoint: this.selectedIntegrationType.url,
|
||||
data: this.testAlert.json,
|
||||
authKey: this.selectedService.authKey,
|
||||
authKey: this.selectedIntegrationType.authKey,
|
||||
})
|
||||
.then(() => {
|
||||
this.setFeedback({
|
||||
|
@ -358,11 +341,11 @@ export default {
|
|||
onReset() {
|
||||
this.testAlert.json = null;
|
||||
this.dismissFeedback();
|
||||
this.targetUrl = this.selectedService.targetUrl;
|
||||
this.targetUrl = this.selectedIntegrationType.targetUrl;
|
||||
|
||||
if (this.canSaveForm) {
|
||||
this.canSaveForm = false;
|
||||
this.active = this.selectedService.activated;
|
||||
this.active = this.selectedIntegrationType.activated;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
@ -370,153 +353,144 @@ export default {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<integrations-list :integrations="integrations" />
|
||||
<gl-form @submit.prevent="onSubmit" @reset.prevent="onReset">
|
||||
<h5 class="gl-font-lg gl-my-5">{{ $options.i18n.integrationsLabel }}</h5>
|
||||
|
||||
<gl-form @submit.prevent="onSubmit" @reset.prevent="onReset">
|
||||
<h5 class="gl-font-lg gl-my-5">{{ $options.i18n.integrationsLabel }}</h5>
|
||||
<gl-alert v-if="showFeedbackMsg" :variant="feedback.variant" @dismiss="dismissFeedback">
|
||||
{{ feedback.feedbackMessage }}
|
||||
<br />
|
||||
<i v-if="serverError">{{ __('Error message:') }} {{ serverError }}</i>
|
||||
<gl-button
|
||||
v-if="showAlertSave"
|
||||
variant="danger"
|
||||
category="primary"
|
||||
class="gl-display-block gl-mt-3"
|
||||
@click="toggle(active)"
|
||||
>
|
||||
{{ __('Save anyway') }}
|
||||
</gl-button>
|
||||
</gl-alert>
|
||||
|
||||
<gl-alert v-if="showFeedbackMsg" :variant="feedback.variant" @dismiss="dismissFeedback">
|
||||
{{ feedback.feedbackMessage }}
|
||||
<br />
|
||||
<i v-if="serverError">{{ __('Error message:') }} {{ serverError }}</i>
|
||||
<gl-button
|
||||
v-if="showAlertSave"
|
||||
variant="danger"
|
||||
category="primary"
|
||||
class="gl-display-block gl-mt-3"
|
||||
@click="toggle(active)"
|
||||
>
|
||||
{{ __('Save anyway') }}
|
||||
</gl-button>
|
||||
</gl-alert>
|
||||
<div data-testid="alert-settings-description">
|
||||
<p v-for="section in sections" :key="section.text">
|
||||
<gl-sprintf :message="section.text">
|
||||
<template #link="{ content }">
|
||||
<gl-link :href="section.url" target="_blank">{{ content }}</gl-link>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div data-testid="alert-settings-description">
|
||||
<p v-for="section in sections" :key="section.text">
|
||||
<gl-sprintf :message="section.text">
|
||||
<template #link="{ content }">
|
||||
<gl-link :href="section.url" target="_blank">{{ content }}</gl-link>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<gl-form-group label-for="integration-type" :label="$options.i18n.integration">
|
||||
<gl-form-select
|
||||
id="integration-type"
|
||||
v-model="selectedEndpoint"
|
||||
:options="options"
|
||||
data-testid="alert-settings-select"
|
||||
@change="resetFormValues"
|
||||
/>
|
||||
<gl-form-group label-for="integration-type" :label="$options.i18n.integration">
|
||||
<gl-form-select
|
||||
id="integration-type"
|
||||
v-model="selectedIntegration"
|
||||
:options="options"
|
||||
data-testid="alert-settings-select"
|
||||
@change="resetFormValues"
|
||||
/>
|
||||
<span class="gl-text-gray-500">
|
||||
<gl-sprintf :message="$options.i18n.integrationsInfo">
|
||||
<template #link="{ content }">
|
||||
<gl-link
|
||||
class="gl-display-inline-block"
|
||||
href="https://gitlab.com/groups/gitlab-org/-/epics/4390"
|
||||
target="_blank"
|
||||
>{{ content }}</gl-link
|
||||
>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</span>
|
||||
</gl-form-group>
|
||||
<gl-form-group :label="$options.i18n.activeLabel" label-for="activated">
|
||||
<toggle-button
|
||||
id="activated"
|
||||
:disabled-input="loading"
|
||||
:is-loading="loading"
|
||||
:value="active"
|
||||
@change="toggleService"
|
||||
/>
|
||||
</gl-form-group>
|
||||
<gl-form-group
|
||||
v-if="isOpsgenie || isPrometheus"
|
||||
:label="$options.i18n.apiBaseUrlLabel"
|
||||
label-for="api-url"
|
||||
>
|
||||
<gl-form-input
|
||||
id="api-url"
|
||||
v-model="targetUrl"
|
||||
type="url"
|
||||
:placeholder="baseUrlPlaceholder"
|
||||
:disabled="!active"
|
||||
/>
|
||||
<span class="gl-text-gray-500">
|
||||
{{ $options.i18n.apiBaseUrlHelpText }}
|
||||
</span>
|
||||
</gl-form-group>
|
||||
<template v-if="!isOpsgenie">
|
||||
<gl-form-group :label="$options.i18n.urlLabel" label-for="url">
|
||||
<gl-form-input-group id="url" readonly :value="selectedIntegrationType.url">
|
||||
<template #append>
|
||||
<clipboard-button
|
||||
:text="selectedIntegrationType.url"
|
||||
:title="$options.i18n.copyToClipboard"
|
||||
class="gl-m-0!"
|
||||
/>
|
||||
</template>
|
||||
</gl-form-input-group>
|
||||
<span class="gl-text-gray-500">
|
||||
<gl-sprintf :message="$options.i18n.integrationsInfo">
|
||||
<template #link="{ content }">
|
||||
<gl-link
|
||||
class="gl-display-inline-block"
|
||||
href="https://gitlab.com/groups/gitlab-org/-/epics/4390"
|
||||
target="_blank"
|
||||
>{{ content }}</gl-link
|
||||
>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
{{ prometheusInfo }}
|
||||
</span>
|
||||
</gl-form-group>
|
||||
<gl-form-group :label="$options.i18n.activeLabel" label-for="activated">
|
||||
<toggle-button
|
||||
id="activated"
|
||||
:disabled-input="loading"
|
||||
:is-loading="loading"
|
||||
:value="active"
|
||||
@change="toggleService"
|
||||
/>
|
||||
<gl-form-group :label="$options.i18n.authKeyLabel" label-for="authorization-key">
|
||||
<gl-form-input-group id="authorization-key" class="gl-mb-2" readonly :value="authKey">
|
||||
<template #append>
|
||||
<clipboard-button
|
||||
:text="authKey"
|
||||
:title="$options.i18n.copyToClipboard"
|
||||
class="gl-m-0!"
|
||||
/>
|
||||
</template>
|
||||
</gl-form-input-group>
|
||||
<gl-button v-gl-modal.authKeyModal :disabled="!active" class="gl-mt-3">{{
|
||||
$options.i18n.resetKey
|
||||
}}</gl-button>
|
||||
<gl-modal
|
||||
modal-id="authKeyModal"
|
||||
:title="$options.i18n.resetKey"
|
||||
:ok-title="$options.i18n.resetKey"
|
||||
ok-variant="danger"
|
||||
@ok="selectedIntegrationType.resetKey"
|
||||
>
|
||||
{{ $options.i18n.restKeyInfo }}
|
||||
</gl-modal>
|
||||
</gl-form-group>
|
||||
<gl-form-group
|
||||
v-if="isOpsgenie || isPrometheus"
|
||||
:label="$options.i18n.apiBaseUrlLabel"
|
||||
label-for="api-url"
|
||||
:label="$options.i18n.alertJson"
|
||||
label-for="alert-json"
|
||||
:invalid-feedback="testAlert.error"
|
||||
>
|
||||
<gl-form-input
|
||||
id="api-url"
|
||||
v-model="targetUrl"
|
||||
type="url"
|
||||
:placeholder="baseUrlPlaceholder"
|
||||
<gl-form-textarea
|
||||
id="alert-json"
|
||||
v-model.trim="testAlert.json"
|
||||
:disabled="!active"
|
||||
:state="jsonIsValid"
|
||||
:placeholder="$options.i18n.alertJsonPlaceholder"
|
||||
rows="6"
|
||||
max-rows="10"
|
||||
/>
|
||||
<span class="gl-text-gray-500">
|
||||
{{ $options.i18n.apiBaseUrlHelpText }}
|
||||
</span>
|
||||
</gl-form-group>
|
||||
<template v-if="!isOpsgenie">
|
||||
<gl-form-group :label="$options.i18n.urlLabel" label-for="url">
|
||||
<gl-form-input-group id="url" readonly :value="selectedService.url">
|
||||
<template #append>
|
||||
<clipboard-button
|
||||
:text="selectedService.url"
|
||||
:title="$options.i18n.copyToClipboard"
|
||||
class="gl-m-0!"
|
||||
/>
|
||||
</template>
|
||||
</gl-form-input-group>
|
||||
<span class="gl-text-gray-500">
|
||||
{{ prometheusInfo }}
|
||||
</span>
|
||||
</gl-form-group>
|
||||
<gl-form-group :label="$options.i18n.authKeyLabel" label-for="authorization-key">
|
||||
<gl-form-input-group id="authorization-key" class="gl-mb-2" readonly :value="authKey">
|
||||
<template #append>
|
||||
<clipboard-button
|
||||
:text="authKey"
|
||||
:title="$options.i18n.copyToClipboard"
|
||||
class="gl-m-0!"
|
||||
/>
|
||||
</template>
|
||||
</gl-form-input-group>
|
||||
<gl-button v-gl-modal.authKeyModal :disabled="!active" class="gl-mt-3">{{
|
||||
$options.i18n.resetKey
|
||||
}}</gl-button>
|
||||
<gl-modal
|
||||
modal-id="authKeyModal"
|
||||
:title="$options.i18n.resetKey"
|
||||
:ok-title="$options.i18n.resetKey"
|
||||
ok-variant="danger"
|
||||
@ok="selectedService.resetKey"
|
||||
>
|
||||
{{ $options.i18n.restKeyInfo }}
|
||||
</gl-modal>
|
||||
</gl-form-group>
|
||||
<gl-form-group
|
||||
:label="$options.i18n.alertJson"
|
||||
label-for="alert-json"
|
||||
:invalid-feedback="testAlert.error"
|
||||
>
|
||||
<gl-form-textarea
|
||||
id="alert-json"
|
||||
v-model.trim="testAlert.json"
|
||||
:disabled="!active"
|
||||
:state="jsonIsValid"
|
||||
:placeholder="$options.i18n.alertJsonPlaceholder"
|
||||
rows="6"
|
||||
max-rows="10"
|
||||
/>
|
||||
</gl-form-group>
|
||||
<gl-button :disabled="!canTestAlert" @click="validateTestAlert">{{
|
||||
$options.i18n.testAlertInfo
|
||||
}}</gl-button>
|
||||
</template>
|
||||
<div class="footer-block row-content-block gl-display-flex gl-justify-content-space-between">
|
||||
<gl-button
|
||||
variant="success"
|
||||
category="primary"
|
||||
:disabled="!canSaveConfig"
|
||||
@click="onSubmit"
|
||||
>
|
||||
{{ __('Save changes') }}
|
||||
</gl-button>
|
||||
<gl-button category="primary" :disabled="!canSaveConfig" @click="onReset">
|
||||
{{ __('Cancel') }}
|
||||
</gl-button>
|
||||
</div>
|
||||
</gl-form>
|
||||
</div>
|
||||
<gl-button :disabled="!canTestAlert" @click="validateTestAlert">{{
|
||||
$options.i18n.testAlertInfo
|
||||
}}</gl-button>
|
||||
</template>
|
||||
<div class="footer-block row-content-block gl-display-flex gl-justify-content-space-between">
|
||||
<gl-button variant="success" category="primary" :disabled="!canSaveConfig" @click="onSubmit">
|
||||
{{ __('Save changes') }}
|
||||
</gl-button>
|
||||
<gl-button category="primary" :disabled="!canSaveConfig" @click="onReset">
|
||||
{{ __('Cancel') }}
|
||||
</gl-button>
|
||||
</div>
|
||||
</gl-form>
|
||||
</template>
|
|
@ -0,0 +1,48 @@
|
|||
<script>
|
||||
import { s__ } from '~/locale';
|
||||
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
||||
import IntegrationsList from './alerts_integrations_list.vue';
|
||||
import SettingsFormOld from './alerts_settings_form_old.vue';
|
||||
import SettingsFormNew from './alerts_settings_form_new.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
IntegrationsList,
|
||||
SettingsFormOld,
|
||||
SettingsFormNew,
|
||||
},
|
||||
mixins: [glFeatureFlagsMixin()],
|
||||
inject: {
|
||||
generic: {
|
||||
default: {},
|
||||
},
|
||||
prometheus: {
|
||||
default: {},
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
integrations() {
|
||||
return [
|
||||
{
|
||||
name: s__('AlertSettings|HTTP endpoint'),
|
||||
type: s__('AlertsIntegrations|HTTP endpoint'),
|
||||
activated: this.generic.activated,
|
||||
},
|
||||
{
|
||||
name: s__('AlertSettings|External Prometheus'),
|
||||
type: s__('AlertsIntegrations|Prometheus'),
|
||||
activated: this.prometheus.activated,
|
||||
},
|
||||
];
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<integrations-list :integrations="integrations" />
|
||||
<settings-form-new v-if="glFeatures.httpIntegrationsList" />
|
||||
<settings-form-old v-else />
|
||||
</div>
|
||||
</template>
|
|
@ -17,11 +17,10 @@ export const i18n = {
|
|||
changesSaved: s__('AlertSettings|Your integration was successfully updated.'),
|
||||
prometheusInfo: s__('AlertSettings|Add URL and auth key to your Prometheus config file'),
|
||||
integrationsInfo: s__(
|
||||
'AlertSettings|Learn more about our improvements for %{linkStart}integrations%{linkEnd}',
|
||||
'AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}',
|
||||
),
|
||||
resetKey: s__('AlertSettings|Reset key'),
|
||||
copyToClipboard: s__('AlertSettings|Copy'),
|
||||
integrationsLabel: s__('AlertSettings|Add new integrations'),
|
||||
apiBaseUrlLabel: s__('AlertSettings|API URL'),
|
||||
authKeyLabel: s__('AlertSettings|Authorization key'),
|
||||
urlLabel: s__('AlertSettings|Webhook URL'),
|
||||
|
@ -40,7 +39,8 @@ export const i18n = {
|
|||
integration: s__('AlertSettings|Integration'),
|
||||
};
|
||||
|
||||
export const serviceOptions = [
|
||||
export const integrationTypes = [
|
||||
{ value: '', text: s__('AlertSettings|Select integration type') },
|
||||
{ value: 'generic', text: s__('AlertSettings|HTTP Endpoint') },
|
||||
{ value: 'prometheus', text: s__('AlertSettings|External Prometheus') },
|
||||
{ value: 'opsgenie', text: s__('AlertSettings|Opsgenie') },
|
||||
|
@ -56,9 +56,9 @@ export const sectionHash = 'js-alert-management-settings';
|
|||
/* eslint-disable @gitlab/require-i18n-strings */
|
||||
|
||||
/**
|
||||
* Tracks snowplow event when user views alerts intergration list
|
||||
* Tracks snowplow event when user views alerts integration list
|
||||
*/
|
||||
export const trackAlertIntergrationsViewsOptions = {
|
||||
category: 'Alert Intergrations',
|
||||
export const trackAlertIntegrationsViewsOptions = {
|
||||
category: 'Alert Integrations',
|
||||
action: 'view_alert_integrations_list',
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import Vue from 'vue';
|
||||
import { parseBoolean } from '~/lib/utils/common_utils';
|
||||
import AlertSettingsForm from './components/alerts_settings_form.vue';
|
||||
import AlertSettingsWrapper from './components/alerts_settings_wrapper.vue';
|
||||
|
||||
export default el => {
|
||||
if (!el) {
|
||||
|
@ -26,16 +26,11 @@ export default el => {
|
|||
opsgenieMvcTargetUrl,
|
||||
} = el.dataset;
|
||||
|
||||
const genericActivated = parseBoolean(activatedStr);
|
||||
const prometheusIsActivated = parseBoolean(prometheusActivated);
|
||||
const opsgenieMvcActivated = parseBoolean(opsgenieMvcEnabled);
|
||||
const opsgenieMvcIsAvailable = parseBoolean(opsgenieMvcAvailable);
|
||||
|
||||
return new Vue({
|
||||
el,
|
||||
provide: {
|
||||
prometheus: {
|
||||
activated: prometheusIsActivated,
|
||||
activated: parseBoolean(prometheusActivated),
|
||||
prometheusUrl,
|
||||
authorizationKey: prometheusAuthorizationKey,
|
||||
prometheusFormPath,
|
||||
|
@ -45,23 +40,23 @@ export default el => {
|
|||
generic: {
|
||||
alertsSetupUrl,
|
||||
alertsUsageUrl,
|
||||
activated: genericActivated,
|
||||
activated: parseBoolean(activatedStr),
|
||||
formPath,
|
||||
authorizationKey,
|
||||
url,
|
||||
},
|
||||
opsgenie: {
|
||||
formPath: opsgenieMvcFormPath,
|
||||
activated: opsgenieMvcActivated,
|
||||
activated: parseBoolean(opsgenieMvcEnabled),
|
||||
opsgenieMvcTargetUrl,
|
||||
opsgenieMvcIsAvailable,
|
||||
opsgenieMvcIsAvailable: parseBoolean(opsgenieMvcAvailable),
|
||||
},
|
||||
},
|
||||
components: {
|
||||
AlertSettingsForm,
|
||||
AlertSettingsWrapper,
|
||||
},
|
||||
render(createElement) {
|
||||
return createElement('alert-settings-form');
|
||||
return createElement('alert-settings-wrapper');
|
||||
},
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
<script>
|
||||
/* eslint-disable vue/no-v-html */
|
||||
import { GlLoadingIcon, GlBadge } from '@gitlab/ui';
|
||||
import { GlLoadingIcon, GlBadge, GlTooltipDirective } from '@gitlab/ui';
|
||||
import { visitUrl } from '../../lib/utils/url_utility';
|
||||
import tooltip from '../../vue_shared/directives/tooltip';
|
||||
import identicon from '../../vue_shared/components/identicon.vue';
|
||||
import eventHub from '../event_hub';
|
||||
import { VISIBILITY_TYPE_ICON, GROUP_VISIBILITY_TYPE } from '../constants';
|
||||
|
@ -17,7 +16,7 @@ import { showLearnGitLabGroupItemPopover } from '~/onboarding_issues';
|
|||
|
||||
export default {
|
||||
directives: {
|
||||
tooltip,
|
||||
GlTooltip: GlTooltipDirective,
|
||||
},
|
||||
components: {
|
||||
GlBadge,
|
||||
|
@ -127,11 +126,10 @@ export default {
|
|||
<div class="group-text flex-grow-1 flex-shrink-1">
|
||||
<div class="d-flex align-items-center flex-wrap title namespace-title gl-mr-3">
|
||||
<a
|
||||
v-tooltip
|
||||
v-gl-tooltip.bottom
|
||||
:href="group.relativePath"
|
||||
:title="group.fullName"
|
||||
class="no-expand gl-mt-3 gl-mr-3 gl-text-gray-900!"
|
||||
data-placement="bottom"
|
||||
>{{
|
||||
// ending bracket must be by closing tag to prevent
|
||||
// link hover text-decoration from over-extending
|
||||
|
|
|
@ -6,6 +6,10 @@ module Projects
|
|||
before_action :authorize_admin_operations!
|
||||
before_action :authorize_read_prometheus_alerts!, only: [:reset_alerting_token]
|
||||
|
||||
before_action do
|
||||
push_frontend_feature_flag(:http_integrations_list, @project)
|
||||
end
|
||||
|
||||
respond_to :json, only: [:reset_alerting_token, :reset_pagerduty_token]
|
||||
|
||||
helper_method :error_tracking_setting
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Resolvers
|
||||
module AlertManagement
|
||||
class IntegrationsResolver < BaseResolver
|
||||
alias_method :project, :synchronized_object
|
||||
|
||||
def resolve(**args)
|
||||
return [] unless Feature.enabled?(:multiple_http_integrations, project)
|
||||
|
||||
http_integrations + prometheus_integrations
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def prometheus_integrations
|
||||
return [] unless Ability.allowed?(current_user, :admin_project, project)
|
||||
|
||||
Array(project.prometheus_service)
|
||||
end
|
||||
|
||||
def http_integrations
|
||||
return [] unless Ability.allowed?(current_user, :admin_operations, project)
|
||||
|
||||
::AlertManagement::HttpIntegrationsFinder.new(project, {}).execute
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
22
app/graphql/types/alert_management/http_integration_type.rb
Normal file
22
app/graphql/types/alert_management/http_integration_type.rb
Normal file
|
@ -0,0 +1,22 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Types
|
||||
module AlertManagement
|
||||
class HttpIntegrationType < BaseObject
|
||||
graphql_name 'AlertManagementHttpIntegration'
|
||||
description 'An endpoint and credentials used to accept alerts for a project'
|
||||
|
||||
implements(Types::AlertManagement::IntegrationType)
|
||||
|
||||
authorize :admin_operations
|
||||
|
||||
def type
|
||||
:http
|
||||
end
|
||||
|
||||
def api_url
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
58
app/graphql/types/alert_management/integration_type.rb
Normal file
58
app/graphql/types/alert_management/integration_type.rb
Normal file
|
@ -0,0 +1,58 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Types
|
||||
module AlertManagement
|
||||
module IntegrationType
|
||||
include Types::BaseInterface
|
||||
graphql_name 'AlertManagementIntegration'
|
||||
|
||||
field :id,
|
||||
GraphQL::ID_TYPE,
|
||||
null: false,
|
||||
description: 'ID of the integration'
|
||||
|
||||
field :type,
|
||||
AlertManagement::IntegrationTypeEnum,
|
||||
null: false,
|
||||
description: 'Type of integration'
|
||||
|
||||
field :name,
|
||||
GraphQL::STRING_TYPE,
|
||||
null: true,
|
||||
description: 'Name of the integration'
|
||||
|
||||
field :active,
|
||||
GraphQL::BOOLEAN_TYPE,
|
||||
null: true,
|
||||
description: 'Whether the endpoint is currently accepting alerts'
|
||||
|
||||
field :token,
|
||||
GraphQL::STRING_TYPE,
|
||||
null: true,
|
||||
description: 'Token used to authenticate alert notification requests'
|
||||
|
||||
field :url,
|
||||
GraphQL::STRING_TYPE,
|
||||
null: true,
|
||||
description: 'Endpoint which accepts alert notifications'
|
||||
|
||||
field :api_url,
|
||||
GraphQL::STRING_TYPE,
|
||||
null: true,
|
||||
description: 'URL at which Prometheus metrics can be queried to populate the metrics dashboard'
|
||||
|
||||
definition_methods do
|
||||
def resolve_type(object, context)
|
||||
if object.is_a?(::PrometheusService)
|
||||
Types::AlertManagement::PrometheusIntegrationType
|
||||
else
|
||||
Types::AlertManagement::HttpIntegrationType
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
orphan_types Types::AlertManagement::PrometheusIntegrationType,
|
||||
Types::AlertManagement::HttpIntegrationType
|
||||
end
|
||||
end
|
||||
end
|
13
app/graphql/types/alert_management/integration_type_enum.rb
Normal file
13
app/graphql/types/alert_management/integration_type_enum.rb
Normal file
|
@ -0,0 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Types
|
||||
module AlertManagement
|
||||
class IntegrationTypeEnum < BaseEnum
|
||||
graphql_name 'AlertManagementIntegrationType'
|
||||
description 'Values of types of integrations'
|
||||
|
||||
value 'PROMETHEUS', 'Prometheus integration', value: :prometheus
|
||||
value 'HTTP', 'Integration with any monitoring tool', value: :http
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,38 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Types
|
||||
module AlertManagement
|
||||
class PrometheusIntegrationType < BaseObject
|
||||
include ::Gitlab::Routing
|
||||
|
||||
graphql_name 'AlertManagementPrometheusIntegration'
|
||||
description 'An endpoint and credentials used to accept Prometheus alerts for a project'
|
||||
|
||||
implements(Types::AlertManagement::IntegrationType)
|
||||
|
||||
authorize :admin_project
|
||||
|
||||
alias_method :prometheus_service, :object
|
||||
|
||||
def name
|
||||
prometheus_service.title
|
||||
end
|
||||
|
||||
def type
|
||||
:prometheus
|
||||
end
|
||||
|
||||
def token
|
||||
prometheus_service.project&.alerting_setting&.token
|
||||
end
|
||||
|
||||
def url
|
||||
prometheus_service.project && notify_project_prometheus_alerts_url(prometheus_service.project, format: :json)
|
||||
end
|
||||
|
||||
def active
|
||||
prometheus_service.manual_configuration?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -267,6 +267,12 @@ module Types
|
|||
description: 'Counts of alerts by status for the project',
|
||||
resolver: Resolvers::AlertManagement::AlertStatusCountsResolver
|
||||
|
||||
field :alert_management_integrations,
|
||||
Types::AlertManagement::IntegrationType.connection_type,
|
||||
null: true,
|
||||
description: 'Integrations which can receive alerts for the project',
|
||||
resolver: Resolvers::AlertManagement::IntegrationsResolver
|
||||
|
||||
field :releases,
|
||||
Types::ReleaseType.connection_type,
|
||||
null: true,
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
module AlertManagement
|
||||
class HttpIntegration < ApplicationRecord
|
||||
include ::Gitlab::Routing
|
||||
LEGACY_IDENTIFIER = 'legacy'
|
||||
DEFAULT_NAME_SLUG = 'http-endpoint'
|
||||
|
||||
|
@ -31,9 +32,9 @@ module AlertManagement
|
|||
scope :ordered_by_id, -> { order(:id) }
|
||||
|
||||
def url
|
||||
return ::Gitlab::Routing.url_helpers.project_alerts_notify_url(project, format: :json) if legacy?
|
||||
return project_alerts_notify_url(project, format: :json) if legacy?
|
||||
|
||||
::Gitlab::Routing.url_helpers.project_alert_http_integration_url(project, name_slug, endpoint_identifier, format: :json)
|
||||
project_alert_http_integration_url(project, name_slug, endpoint_identifier, format: :json)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
7
app/policies/alert_management/http_integration_policy.rb
Normal file
7
app/policies/alert_management/http_integration_policy.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module AlertManagement
|
||||
class HttpIntegrationPolicy < ::BasePolicy
|
||||
delegate { @subject.project }
|
||||
end
|
||||
end
|
5
app/policies/prometheus_service_policy.rb
Normal file
5
app/policies/prometheus_service_policy.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class PrometheusServicePolicy < ::BasePolicy
|
||||
delegate { @subject.project }
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Disallow some project routes in robots.txt
|
||||
merge_request: 46218
|
||||
author:
|
||||
type: changed
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
name: http_integrations_list
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45993
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/255502
|
||||
type: development
|
||||
group: group::health
|
||||
default_enabled: false
|
|
@ -590,6 +590,173 @@ type AlertManagementAlertStatusCountsType {
|
|||
triggered: Int
|
||||
}
|
||||
|
||||
"""
|
||||
An endpoint and credentials used to accept alerts for a project
|
||||
"""
|
||||
type AlertManagementHttpIntegration implements AlertManagementIntegration {
|
||||
"""
|
||||
Whether the endpoint is currently accepting alerts
|
||||
"""
|
||||
active: Boolean
|
||||
|
||||
"""
|
||||
URL at which Prometheus metrics can be queried to populate the metrics dashboard
|
||||
"""
|
||||
apiUrl: String
|
||||
|
||||
"""
|
||||
ID of the integration
|
||||
"""
|
||||
id: ID!
|
||||
|
||||
"""
|
||||
Name of the integration
|
||||
"""
|
||||
name: String
|
||||
|
||||
"""
|
||||
Token used to authenticate alert notification requests
|
||||
"""
|
||||
token: String
|
||||
|
||||
"""
|
||||
Type of integration
|
||||
"""
|
||||
type: AlertManagementIntegrationType!
|
||||
|
||||
"""
|
||||
Endpoint which accepts alert notifications
|
||||
"""
|
||||
url: String
|
||||
}
|
||||
|
||||
interface AlertManagementIntegration {
|
||||
"""
|
||||
Whether the endpoint is currently accepting alerts
|
||||
"""
|
||||
active: Boolean
|
||||
|
||||
"""
|
||||
URL at which Prometheus metrics can be queried to populate the metrics dashboard
|
||||
"""
|
||||
apiUrl: String
|
||||
|
||||
"""
|
||||
ID of the integration
|
||||
"""
|
||||
id: ID!
|
||||
|
||||
"""
|
||||
Name of the integration
|
||||
"""
|
||||
name: String
|
||||
|
||||
"""
|
||||
Token used to authenticate alert notification requests
|
||||
"""
|
||||
token: String
|
||||
|
||||
"""
|
||||
Type of integration
|
||||
"""
|
||||
type: AlertManagementIntegrationType!
|
||||
|
||||
"""
|
||||
Endpoint which accepts alert notifications
|
||||
"""
|
||||
url: String
|
||||
}
|
||||
|
||||
"""
|
||||
The connection type for AlertManagementIntegration.
|
||||
"""
|
||||
type AlertManagementIntegrationConnection {
|
||||
"""
|
||||
A list of edges.
|
||||
"""
|
||||
edges: [AlertManagementIntegrationEdge]
|
||||
|
||||
"""
|
||||
A list of nodes.
|
||||
"""
|
||||
nodes: [AlertManagementIntegration]
|
||||
|
||||
"""
|
||||
Information to aid in pagination.
|
||||
"""
|
||||
pageInfo: PageInfo!
|
||||
}
|
||||
|
||||
"""
|
||||
An edge in a connection.
|
||||
"""
|
||||
type AlertManagementIntegrationEdge {
|
||||
"""
|
||||
A cursor for use in pagination.
|
||||
"""
|
||||
cursor: String!
|
||||
|
||||
"""
|
||||
The item at the end of the edge.
|
||||
"""
|
||||
node: AlertManagementIntegration
|
||||
}
|
||||
|
||||
"""
|
||||
Values of types of integrations
|
||||
"""
|
||||
enum AlertManagementIntegrationType {
|
||||
"""
|
||||
Integration with any monitoring tool
|
||||
"""
|
||||
HTTP
|
||||
|
||||
"""
|
||||
Prometheus integration
|
||||
"""
|
||||
PROMETHEUS
|
||||
}
|
||||
|
||||
"""
|
||||
An endpoint and credentials used to accept Prometheus alerts for a project
|
||||
"""
|
||||
type AlertManagementPrometheusIntegration implements AlertManagementIntegration {
|
||||
"""
|
||||
Whether the endpoint is currently accepting alerts
|
||||
"""
|
||||
active: Boolean
|
||||
|
||||
"""
|
||||
URL at which Prometheus metrics can be queried to populate the metrics dashboard
|
||||
"""
|
||||
apiUrl: String
|
||||
|
||||
"""
|
||||
ID of the integration
|
||||
"""
|
||||
id: ID!
|
||||
|
||||
"""
|
||||
Name of the integration
|
||||
"""
|
||||
name: String
|
||||
|
||||
"""
|
||||
Token used to authenticate alert notification requests
|
||||
"""
|
||||
token: String
|
||||
|
||||
"""
|
||||
Type of integration
|
||||
"""
|
||||
type: AlertManagementIntegrationType!
|
||||
|
||||
"""
|
||||
Endpoint which accepts alert notifications
|
||||
"""
|
||||
url: String
|
||||
}
|
||||
|
||||
"""
|
||||
Alert severity values
|
||||
"""
|
||||
|
@ -13747,6 +13914,31 @@ type Project {
|
|||
statuses: [AlertManagementStatus!]
|
||||
): AlertManagementAlertConnection
|
||||
|
||||
"""
|
||||
Integrations which can receive alerts for the project
|
||||
"""
|
||||
alertManagementIntegrations(
|
||||
"""
|
||||
Returns the elements in the list that come after the specified cursor.
|
||||
"""
|
||||
after: String
|
||||
|
||||
"""
|
||||
Returns the elements in the list that come before the specified cursor.
|
||||
"""
|
||||
before: String
|
||||
|
||||
"""
|
||||
Returns the first _n_ elements from the list.
|
||||
"""
|
||||
first: Int
|
||||
|
||||
"""
|
||||
Returns the last _n_ elements from the list.
|
||||
"""
|
||||
last: Int
|
||||
): AlertManagementIntegrationConnection
|
||||
|
||||
"""
|
||||
If `only_allow_merge_if_pipeline_succeeds` is true, indicates if merge
|
||||
requests of the project can also be merged with skipped jobs
|
||||
|
|
|
@ -1480,6 +1480,515 @@
|
|||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "AlertManagementHttpIntegration",
|
||||
"description": "An endpoint and credentials used to accept alerts for a project",
|
||||
"fields": [
|
||||
{
|
||||
"name": "active",
|
||||
"description": "Whether the endpoint is currently accepting alerts",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "Boolean",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "apiUrl",
|
||||
"description": "URL at which Prometheus metrics can be queried to populate the metrics dashboard",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "id",
|
||||
"description": "ID of the integration",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "ID",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"description": "Name of the integration",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "token",
|
||||
"description": "Token used to authenticate alert notification requests",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "type",
|
||||
"description": "Type of integration",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "ENUM",
|
||||
"name": "AlertManagementIntegrationType",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "url",
|
||||
"description": "Endpoint which accepts alert notifications",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"inputFields": null,
|
||||
"interfaces": [
|
||||
{
|
||||
"kind": "INTERFACE",
|
||||
"name": "AlertManagementIntegration",
|
||||
"ofType": null
|
||||
}
|
||||
],
|
||||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "INTERFACE",
|
||||
"name": "AlertManagementIntegration",
|
||||
"description": null,
|
||||
"fields": [
|
||||
{
|
||||
"name": "active",
|
||||
"description": "Whether the endpoint is currently accepting alerts",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "Boolean",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "apiUrl",
|
||||
"description": "URL at which Prometheus metrics can be queried to populate the metrics dashboard",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "id",
|
||||
"description": "ID of the integration",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "ID",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"description": "Name of the integration",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "token",
|
||||
"description": "Token used to authenticate alert notification requests",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "type",
|
||||
"description": "Type of integration",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "ENUM",
|
||||
"name": "AlertManagementIntegrationType",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "url",
|
||||
"description": "Endpoint which accepts alert notifications",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"inputFields": null,
|
||||
"interfaces": null,
|
||||
"enumValues": null,
|
||||
"possibleTypes": [
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "AlertManagementHttpIntegration",
|
||||
"ofType": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "AlertManagementPrometheusIntegration",
|
||||
"ofType": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "AlertManagementIntegrationConnection",
|
||||
"description": "The connection type for AlertManagementIntegration.",
|
||||
"fields": [
|
||||
{
|
||||
"name": "edges",
|
||||
"description": "A list of edges.",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "LIST",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "OBJECT",
|
||||
"name": "AlertManagementIntegrationEdge",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "nodes",
|
||||
"description": "A list of nodes.",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "LIST",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "INTERFACE",
|
||||
"name": "AlertManagementIntegration",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "pageInfo",
|
||||
"description": "Information to aid in pagination.",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "OBJECT",
|
||||
"name": "PageInfo",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"inputFields": null,
|
||||
"interfaces": [
|
||||
|
||||
],
|
||||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "AlertManagementIntegrationEdge",
|
||||
"description": "An edge in a connection.",
|
||||
"fields": [
|
||||
{
|
||||
"name": "cursor",
|
||||
"description": "A cursor for use in pagination.",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "node",
|
||||
"description": "The item at the end of the edge.",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "INTERFACE",
|
||||
"name": "AlertManagementIntegration",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"inputFields": null,
|
||||
"interfaces": [
|
||||
|
||||
],
|
||||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "ENUM",
|
||||
"name": "AlertManagementIntegrationType",
|
||||
"description": "Values of types of integrations",
|
||||
"fields": null,
|
||||
"inputFields": null,
|
||||
"interfaces": null,
|
||||
"enumValues": [
|
||||
{
|
||||
"name": "PROMETHEUS",
|
||||
"description": "Prometheus integration",
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "HTTP",
|
||||
"description": "Integration with any monitoring tool",
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "AlertManagementPrometheusIntegration",
|
||||
"description": "An endpoint and credentials used to accept Prometheus alerts for a project",
|
||||
"fields": [
|
||||
{
|
||||
"name": "active",
|
||||
"description": "Whether the endpoint is currently accepting alerts",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "Boolean",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "apiUrl",
|
||||
"description": "URL at which Prometheus metrics can be queried to populate the metrics dashboard",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "id",
|
||||
"description": "ID of the integration",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "ID",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"description": "Name of the integration",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "token",
|
||||
"description": "Token used to authenticate alert notification requests",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "type",
|
||||
"description": "Type of integration",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "ENUM",
|
||||
"name": "AlertManagementIntegrationType",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "url",
|
||||
"description": "Endpoint which accepts alert notifications",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"inputFields": null,
|
||||
"interfaces": [
|
||||
{
|
||||
"kind": "INTERFACE",
|
||||
"name": "AlertManagementIntegration",
|
||||
"ofType": null
|
||||
}
|
||||
],
|
||||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "ENUM",
|
||||
"name": "AlertManagementSeverity",
|
||||
|
@ -40456,6 +40965,59 @@
|
|||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "alertManagementIntegrations",
|
||||
"description": "Integrations which can receive alerts for the project",
|
||||
"args": [
|
||||
{
|
||||
"name": "after",
|
||||
"description": "Returns the elements in the list that come after the specified cursor.",
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "before",
|
||||
"description": "Returns the elements in the list that come before the specified cursor.",
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "first",
|
||||
"description": "Returns the first _n_ elements from the list.",
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "Int",
|
||||
"ofType": null
|
||||
},
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "last",
|
||||
"description": "Returns the last _n_ elements from the list.",
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "Int",
|
||||
"ofType": null
|
||||
},
|
||||
"defaultValue": null
|
||||
}
|
||||
],
|
||||
"type": {
|
||||
"kind": "OBJECT",
|
||||
"name": "AlertManagementIntegrationConnection",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "allowMergeOnSkippedPipeline",
|
||||
"description": "If `only_allow_merge_if_pipeline_succeeds` is true, indicates if merge requests of the project can also be merged with skipped jobs",
|
||||
|
|
|
@ -106,6 +106,34 @@ Represents total number of alerts for the represented categories.
|
|||
| `resolved` | Int | Number of alerts with status RESOLVED for the project |
|
||||
| `triggered` | Int | Number of alerts with status TRIGGERED for the project |
|
||||
|
||||
### AlertManagementHttpIntegration
|
||||
|
||||
An endpoint and credentials used to accept alerts for a project.
|
||||
|
||||
| Field | Type | Description |
|
||||
| ----- | ---- | ----------- |
|
||||
| `active` | Boolean | Whether the endpoint is currently accepting alerts |
|
||||
| `apiUrl` | String | URL at which Prometheus metrics can be queried to populate the metrics dashboard |
|
||||
| `id` | ID! | ID of the integration |
|
||||
| `name` | String | Name of the integration |
|
||||
| `token` | String | Token used to authenticate alert notification requests |
|
||||
| `type` | AlertManagementIntegrationType! | Type of integration |
|
||||
| `url` | String | Endpoint which accepts alert notifications |
|
||||
|
||||
### AlertManagementPrometheusIntegration
|
||||
|
||||
An endpoint and credentials used to accept Prometheus alerts for a project.
|
||||
|
||||
| Field | Type | Description |
|
||||
| ----- | ---- | ----------- |
|
||||
| `active` | Boolean | Whether the endpoint is currently accepting alerts |
|
||||
| `apiUrl` | String | URL at which Prometheus metrics can be queried to populate the metrics dashboard |
|
||||
| `id` | ID! | ID of the integration |
|
||||
| `name` | String | Name of the integration |
|
||||
| `token` | String | Token used to authenticate alert notification requests |
|
||||
| `type` | AlertManagementIntegrationType! | Type of integration |
|
||||
| `url` | String | Endpoint which accepts alert notifications |
|
||||
|
||||
### AlertSetAssigneesPayload
|
||||
|
||||
Autogenerated return type of AlertSetAssignees.
|
||||
|
@ -3241,6 +3269,15 @@ Values for sorting alerts.
|
|||
| `updated_asc` **{warning-solid}** | **Deprecated:** Use UPDATED_ASC. Deprecated in 13.5 |
|
||||
| `updated_desc` **{warning-solid}** | **Deprecated:** Use UPDATED_DESC. Deprecated in 13.5 |
|
||||
|
||||
### AlertManagementIntegrationType
|
||||
|
||||
Values of types of integrations.
|
||||
|
||||
| Value | Description |
|
||||
| ----- | ----------- |
|
||||
| `HTTP` | Integration with any monitoring tool |
|
||||
| `PROMETHEUS` | Prometheus integration |
|
||||
|
||||
### AlertManagementSeverity
|
||||
|
||||
Alert severity values.
|
||||
|
|
|
@ -136,14 +136,26 @@ curl --data "name=foo" --header "PRIVATE-TOKEN: <your_access_token>" "https://gi
|
|||
|
||||
### Post data using JSON content
|
||||
|
||||
NOTE: **Note:**
|
||||
In this example we create a new group. Watch carefully the single and double
|
||||
quotes.
|
||||
This example creates a new group. Be aware of the use of single (`'`) and double
|
||||
(`"`) quotes.
|
||||
|
||||
```shell
|
||||
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" --data '{"path": "my-group", "name": "My group"}' "https://gitlab.example.com/api/v4/groups"
|
||||
```
|
||||
|
||||
For readability, you can also set up the `--data` by using the following format:
|
||||
|
||||
```shell
|
||||
curl --request POST \
|
||||
--url "https://gitlab.example.com/api/v4/groups" \
|
||||
--header "content-type: application/json" \
|
||||
--header "PRIVATE-TOKEN: <your_access_token>" \
|
||||
--data '{
|
||||
"path": "my-group",
|
||||
"name": "My group"
|
||||
}'
|
||||
```
|
||||
|
||||
### Post data using form-data
|
||||
|
||||
Instead of using JSON or urlencode you can use multipart/form-data which
|
||||
|
|
|
@ -248,6 +248,11 @@ It is recommended to use the `debug` level for verbose logging that could be
|
|||
useful when debugging. The default value for `SECURE_LOG_LEVEL` should be set
|
||||
to `info`.
|
||||
|
||||
When executing command lines, scanners should use the `debug` level to log the command line and its output.
|
||||
For instance, the [bundler-audit](https://gitlab.com/gitlab-org/security-products/analyzers/bundler-audit) scanner
|
||||
uses the `debug` level to log the command line `bundle audit check --quiet`,
|
||||
and what `bundle audit` writes to the standard output.
|
||||
|
||||
#### common logutil package
|
||||
|
||||
If you are using [go](https://golang.org/) and
|
||||
|
|
|
@ -4,7 +4,7 @@ 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
|
||||
---
|
||||
|
||||
# Monitor your CI/CD environment's metrics **(CORE)**
|
||||
# Monitor your environment's metrics **(CORE)**
|
||||
|
||||
GitLab helps your team monitor the health and performance of your applications
|
||||
and infrastructure by turning statistics and log files into charts and graphs
|
||||
|
|
|
@ -714,10 +714,6 @@ To delete a scanner profile:
|
|||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218465) in GitLab 13.2.
|
||||
> - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/218465) in GitLab 13.3.
|
||||
> - It's deployed behind a feature flag, enabled by default.
|
||||
> - It's enabled on GitLab.com.
|
||||
> - It's able to be enabled or disabled per-project.
|
||||
> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-on-demand-scans).
|
||||
|
||||
An on-demand DAST scan runs outside the DevOps life cycle. Changes in your repository don't trigger
|
||||
the scan. You must start it manually.
|
||||
|
@ -748,35 +744,6 @@ To run an on-demand DAST scan, you need:
|
|||
|
||||
The on-demand DAST scan runs and the project's dashboard shows the results.
|
||||
|
||||
### Enable or disable On-demand Scans
|
||||
|
||||
The On-demand DAST Scans feature is enabled by default. You can disable on-demand scans
|
||||
instance-wide, or disable it for specific projects if you prefer.
|
||||
|
||||
To run on-demand DAST scans, an administrator must enable the
|
||||
`security_on_demand_scans_feature_flag` feature flag.
|
||||
|
||||
[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
|
||||
can disable or enable the feature flags.
|
||||
|
||||
To disable On-demand DAST Scans:
|
||||
|
||||
```ruby
|
||||
# Instance-wide
|
||||
Feature.disable(:security_on_demand_scans_feature_flag)
|
||||
# or by project
|
||||
Feature.disable(:security_on_demand_scans_feature_flag, Project.find(<project id>))
|
||||
```
|
||||
|
||||
To enable On-demand DAST Scans:
|
||||
|
||||
```ruby
|
||||
# Instance-wide
|
||||
Feature.enable(:security_on_demand_scans_feature_flag)
|
||||
# or by project
|
||||
Feature.enable(:security_on_demand_scans_feature_flag, Project.find(<project ID>))
|
||||
```
|
||||
|
||||
## Reports
|
||||
|
||||
The DAST tool outputs a report file in JSON format by default. However, this tool can also generate reports in
|
||||
|
|
|
@ -2486,6 +2486,12 @@ msgstr ""
|
|||
msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
|
||||
msgstr ""
|
||||
|
||||
msgid "AlertSettings|1. Select integration type"
|
||||
msgstr ""
|
||||
|
||||
msgid "AlertSettings|2. Name integration"
|
||||
msgstr ""
|
||||
|
||||
msgid "AlertSettings|API URL"
|
||||
msgstr ""
|
||||
|
||||
|
@ -2510,6 +2516,9 @@ msgstr ""
|
|||
msgid "AlertSettings|Copy"
|
||||
msgstr ""
|
||||
|
||||
msgid "AlertSettings|Enter integration name"
|
||||
msgstr ""
|
||||
|
||||
msgid "AlertSettings|Enter test alert JSON...."
|
||||
msgstr ""
|
||||
|
||||
|
@ -2525,7 +2534,10 @@ msgstr ""
|
|||
msgid "AlertSettings|Integration"
|
||||
msgstr ""
|
||||
|
||||
msgid "AlertSettings|Learn more about our improvements for %{linkStart}integrations%{linkEnd}"
|
||||
msgid "AlertSettings|Learn more about our our upcoming %{linkStart}integrations%{linkEnd}"
|
||||
msgstr ""
|
||||
|
||||
msgid "AlertSettings|Learn more about our upcoming %{linkStart}integrations%{linkEnd}"
|
||||
msgstr ""
|
||||
|
||||
msgid "AlertSettings|Opsgenie"
|
||||
|
@ -2540,6 +2552,12 @@ msgstr ""
|
|||
msgid "AlertSettings|Review your external service's documentation to learn where to provide this information to your external service, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint."
|
||||
msgstr ""
|
||||
|
||||
msgid "AlertSettings|Save integration"
|
||||
msgstr ""
|
||||
|
||||
msgid "AlertSettings|Select integration type"
|
||||
msgstr ""
|
||||
|
||||
msgid "AlertSettings|Test alert payload"
|
||||
msgstr ""
|
||||
|
||||
|
@ -23040,6 +23058,9 @@ msgstr ""
|
|||
msgid "Save Push Rules"
|
||||
msgstr ""
|
||||
|
||||
msgid "Save and test payload"
|
||||
msgstr ""
|
||||
|
||||
msgid "Save anyway"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -67,3 +67,16 @@ Disallow: /*/protected_branches
|
|||
Disallow: /*/uploads/
|
||||
Disallow: /*/project_members
|
||||
Disallow: /*/settings
|
||||
Disallow: /*/-/import
|
||||
Disallow: /*/-/environments
|
||||
Disallow: /*/-/jobs
|
||||
Disallow: /*/-/requirements_management
|
||||
Disallow: /*/-/pipelines
|
||||
Disallow: /*/-/pipeline_schedules
|
||||
Disallow: /*/-/dependencies
|
||||
Disallow: /*/-/licenses
|
||||
Disallow: /*/-/metrics
|
||||
Disallow: /*/-/incidents
|
||||
Disallow: /*/-/value_stream_analytics
|
||||
Disallow: /*/-/analytics
|
||||
Disallow: /*/insights
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# When running in CI environment, we need to load a full `spec_helper`
|
||||
if ENV['CI']
|
||||
require_relative 'spec_helper'
|
||||
return
|
||||
end
|
||||
|
||||
require 'bundler/setup'
|
||||
|
||||
ENV['GITLAB_ENV'] = 'test'
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'Alert integrations settings form', :js do
|
||||
let_it_be(:project) { create(:project) }
|
||||
let_it_be(:maintainer) { create(:user) }
|
||||
let_it_be(:developer) { create(:user) }
|
||||
|
||||
before_all do
|
||||
project.add_maintainer(maintainer)
|
||||
project.add_developer(developer)
|
||||
end
|
||||
|
||||
before do
|
||||
sign_in(maintainer)
|
||||
end
|
||||
|
||||
describe 'when viewing alert integrations as a maintainer' do
|
||||
context 'with feature flag enabled' do
|
||||
before do
|
||||
visit project_settings_operations_path(project, anchor: 'js-alert-management-settings')
|
||||
wait_for_requests
|
||||
end
|
||||
|
||||
it 'shows the alerts setting form title' do
|
||||
page.within('#js-alert-management-settings') do
|
||||
expect(find('h3')).to have_content('Alerts')
|
||||
end
|
||||
end
|
||||
|
||||
it 'shows the new alerts setting form' do
|
||||
expect(page).to have_content('1. Select integration type')
|
||||
end
|
||||
end
|
||||
|
||||
context 'with feature flag disabled' do
|
||||
before do
|
||||
stub_feature_flags(http_integrations_list: false)
|
||||
|
||||
visit project_settings_operations_path(project, anchor: 'js-alert-management-settings')
|
||||
wait_for_requests
|
||||
end
|
||||
|
||||
it 'shows the old alerts setting form' do
|
||||
expect(page).to have_content('Webhook URL')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when viewing alert integrations as a developer' do
|
||||
before do
|
||||
sign_in(developer)
|
||||
|
||||
visit project_settings_operations_path(project, anchor: 'js-alert-management-settings')
|
||||
wait_for_requests
|
||||
end
|
||||
|
||||
it 'shows the old alerts setting form' do
|
||||
expect(page).not_to have_selector('.incident-management-list')
|
||||
expect(page).not_to have_selector('#js-alert-management-settings')
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,50 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`AlertsSettingsForm with default values renders the initial template 1`] = `
|
||||
"<div>
|
||||
<integrations-list-stub integrations=\\"[object Object],[object Object]\\"></integrations-list-stub>
|
||||
<gl-form-stub>
|
||||
<h5 class=\\"gl-font-lg gl-my-5\\">Add new integrations</h5>
|
||||
<!---->
|
||||
<div data-testid=\\"alert-settings-description\\">
|
||||
<p>
|
||||
<gl-sprintf-stub message=\\"You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page.\\"></gl-sprintf-stub>
|
||||
</p>
|
||||
<p>
|
||||
<gl-sprintf-stub message=\\"Review your external service's documentation to learn where to provide this information to your external service, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint.\\"></gl-sprintf-stub>
|
||||
</p>
|
||||
</div>
|
||||
<gl-form-group-stub label-for=\\"integration-type\\" label=\\"Integration\\">
|
||||
<gl-form-select-stub id=\\"integration-type\\" options=\\"[object Object],[object Object],[object Object]\\" data-testid=\\"alert-settings-select\\" value=\\"generic\\"></gl-form-select-stub> <span class=\\"gl-text-gray-500\\"><gl-sprintf-stub message=\\"Learn more about our improvements for %{linkStart}integrations%{linkEnd}\\"></gl-sprintf-stub></span>
|
||||
</gl-form-group-stub>
|
||||
<gl-form-group-stub label=\\"Active\\" label-for=\\"activated\\">
|
||||
<toggle-button-stub id=\\"activated\\"></toggle-button-stub>
|
||||
</gl-form-group-stub>
|
||||
<!---->
|
||||
<gl-form-group-stub label=\\"Webhook URL\\" label-for=\\"url\\">
|
||||
<gl-form-input-group-stub value=\\"/alerts/notify.json\\" predefinedoptions=\\"[object Object]\\" id=\\"url\\" readonly=\\"\\"></gl-form-input-group-stub> <span class=\\"gl-text-gray-500\\">
|
||||
|
||||
</span>
|
||||
</gl-form-group-stub>
|
||||
<gl-form-group-stub label=\\"Authorization key\\" label-for=\\"authorization-key\\">
|
||||
<gl-form-input-group-stub value=\\"abcedfg123\\" predefinedoptions=\\"[object Object]\\" id=\\"authorization-key\\" readonly=\\"\\" class=\\"gl-mb-2\\"></gl-form-input-group-stub>
|
||||
<gl-button-stub category=\\"primary\\" variant=\\"default\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" disabled=\\"true\\" class=\\"gl-mt-3\\" role=\\"button\\" tabindex=\\"0\\">Reset key</gl-button-stub>
|
||||
<gl-modal-stub modalid=\\"authKeyModal\\" titletag=\\"h4\\" modalclass=\\"\\" size=\\"md\\" title=\\"Reset key\\" ok-title=\\"Reset key\\" ok-variant=\\"danger\\">
|
||||
Resetting the authorization key for this project will require updating the authorization key in every alert source it is enabled in.
|
||||
</gl-modal-stub>
|
||||
</gl-form-group-stub>
|
||||
<gl-form-group-stub label=\\"Alert test payload\\" label-for=\\"alert-json\\">
|
||||
<gl-form-textarea-stub noresize=\\"true\\" id=\\"alert-json\\" disabled=\\"true\\" state=\\"true\\" placeholder=\\"Enter test alert JSON....\\" rows=\\"6\\" max-rows=\\"10\\"></gl-form-textarea-stub>
|
||||
</gl-form-group-stub>
|
||||
<gl-button-stub category=\\"primary\\" variant=\\"default\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" disabled=\\"true\\">Test alert payload</gl-button-stub>
|
||||
<div class=\\"footer-block row-content-block gl-display-flex gl-justify-content-space-between\\">
|
||||
<gl-button-stub category=\\"primary\\" variant=\\"success\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" disabled=\\"true\\">
|
||||
Save changes
|
||||
</gl-button-stub>
|
||||
<gl-button-stub category=\\"primary\\" variant=\\"default\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" disabled=\\"true\\">
|
||||
Cancel
|
||||
</gl-button-stub>
|
||||
</div>
|
||||
</gl-form-stub>
|
||||
</div>"
|
||||
`;
|
|
@ -0,0 +1,20 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`AlertsSettingsFormNew with default values renders the initial template 1`] = `
|
||||
"<gl-form-stub class=\\"gl-mt-6\\">
|
||||
<h5 class=\\"gl-font-lg gl-my-5\\">Add new integrations</h5>
|
||||
<gl-form-group-stub id=\\"integration-type\\" label=\\"1. Select integration type\\" label-for=\\"integration-type\\">
|
||||
<gl-form-select-stub id=\\"integration-type\\" options=\\"[object Object],[object Object],[object Object],[object Object]\\" value=\\"\\"></gl-form-select-stub> <span class=\\"gl-text-gray-500\\"><gl-sprintf-stub message=\\"Learn more about our upcoming %{linkStart}integrations%{linkEnd}\\"></gl-sprintf-stub></span>
|
||||
</gl-form-group-stub>
|
||||
<b-collapse-stub tag=\\"div\\" class=\\"gl-mt-3\\">
|
||||
<gl-form-group-stub id=\\"name-integration\\" label=\\"2. Name integration\\" label-for=\\"name-integration\\">
|
||||
<b-form-input-stub id=\\"name-integration\\" value=\\"\\" placeholder=\\"Enter integration name\\" debounce=\\"0\\" type=\\"text\\" class=\\"gl-form-input\\"></b-form-input-stub>
|
||||
</gl-form-group-stub>
|
||||
<div class=\\"gl-display-flex gl-justify-content-end\\">
|
||||
<gl-button-stub category=\\"primary\\" variant=\\"default\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" type=\\"reset\\" class=\\"gl-mr-3 js-no-auto-disable\\">Cancel</gl-button-stub>
|
||||
<gl-button-stub category=\\"secondary\\" variant=\\"success\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" type=\\"submit\\" class=\\"gl-mr-1 js-no-auto-disable\\">Save and test payload</gl-button-stub>
|
||||
<gl-button-stub category=\\"primary\\" variant=\\"success\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" type=\\"submit\\" class=\\"js-no-auto-disable\\">Save integration</gl-button-stub>
|
||||
</div>
|
||||
</b-collapse-stub>
|
||||
</gl-form-stub>"
|
||||
`;
|
|
@ -0,0 +1,47 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`AlertsSettingsForm with default values renders the initial template 1`] = `
|
||||
"<gl-form-stub>
|
||||
<h5 class=\\"gl-font-lg gl-my-5\\"></h5>
|
||||
<!---->
|
||||
<div data-testid=\\"alert-settings-description\\">
|
||||
<p>
|
||||
<gl-sprintf-stub message=\\"You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page.\\"></gl-sprintf-stub>
|
||||
</p>
|
||||
<p>
|
||||
<gl-sprintf-stub message=\\"Review your external service's documentation to learn where to provide this information to your external service, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint.\\"></gl-sprintf-stub>
|
||||
</p>
|
||||
</div>
|
||||
<gl-form-group-stub label-for=\\"integration-type\\" label=\\"Integration\\">
|
||||
<gl-form-select-stub id=\\"integration-type\\" options=\\"[object Object],[object Object],[object Object],[object Object]\\" data-testid=\\"alert-settings-select\\" value=\\"generic\\"></gl-form-select-stub> <span class=\\"gl-text-gray-500\\"><gl-sprintf-stub message=\\"Learn more about our our upcoming %{linkStart}integrations%{linkEnd}\\"></gl-sprintf-stub></span>
|
||||
</gl-form-group-stub>
|
||||
<gl-form-group-stub label=\\"Active\\" label-for=\\"activated\\">
|
||||
<toggle-button-stub id=\\"activated\\"></toggle-button-stub>
|
||||
</gl-form-group-stub>
|
||||
<!---->
|
||||
<gl-form-group-stub label=\\"Webhook URL\\" label-for=\\"url\\">
|
||||
<gl-form-input-group-stub value=\\"/alerts/notify.json\\" predefinedoptions=\\"[object Object]\\" id=\\"url\\" readonly=\\"\\"></gl-form-input-group-stub> <span class=\\"gl-text-gray-500\\">
|
||||
|
||||
</span>
|
||||
</gl-form-group-stub>
|
||||
<gl-form-group-stub label=\\"Authorization key\\" label-for=\\"authorization-key\\">
|
||||
<gl-form-input-group-stub value=\\"abcedfg123\\" predefinedoptions=\\"[object Object]\\" id=\\"authorization-key\\" readonly=\\"\\" class=\\"gl-mb-2\\"></gl-form-input-group-stub>
|
||||
<gl-button-stub category=\\"primary\\" variant=\\"default\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" disabled=\\"true\\" class=\\"gl-mt-3\\" role=\\"button\\" tabindex=\\"0\\">Reset key</gl-button-stub>
|
||||
<gl-modal-stub modalid=\\"authKeyModal\\" titletag=\\"h4\\" modalclass=\\"\\" size=\\"md\\" title=\\"Reset key\\" ok-title=\\"Reset key\\" ok-variant=\\"danger\\">
|
||||
Resetting the authorization key for this project will require updating the authorization key in every alert source it is enabled in.
|
||||
</gl-modal-stub>
|
||||
</gl-form-group-stub>
|
||||
<gl-form-group-stub label=\\"Alert test payload\\" label-for=\\"alert-json\\">
|
||||
<gl-form-textarea-stub noresize=\\"true\\" id=\\"alert-json\\" disabled=\\"true\\" state=\\"true\\" placeholder=\\"Enter test alert JSON....\\" rows=\\"6\\" max-rows=\\"10\\"></gl-form-textarea-stub>
|
||||
</gl-form-group-stub>
|
||||
<gl-button-stub category=\\"primary\\" variant=\\"default\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" disabled=\\"true\\">Test alert payload</gl-button-stub>
|
||||
<div class=\\"footer-block row-content-block gl-display-flex gl-justify-content-space-between\\">
|
||||
<gl-button-stub category=\\"primary\\" variant=\\"success\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" disabled=\\"true\\">
|
||||
Save changes
|
||||
</gl-button-stub>
|
||||
<gl-button-stub category=\\"primary\\" variant=\\"default\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" disabled=\\"true\\">
|
||||
Cancel
|
||||
</gl-button-stub>
|
||||
</div>
|
||||
</gl-form-stub>"
|
||||
`;
|
|
@ -4,7 +4,7 @@ import Tracking from '~/tracking';
|
|||
import AlertIntegrationsList, {
|
||||
i18n,
|
||||
} from '~/alerts_settings/components/alerts_integrations_list.vue';
|
||||
import { trackAlertIntergrationsViewsOptions } from '~/alerts_settings/constants';
|
||||
import { trackAlertIntegrationsViewsOptions } from '~/alerts_settings/constants';
|
||||
|
||||
const mockIntegrations = [
|
||||
{
|
||||
|
@ -82,7 +82,7 @@ describe('AlertIntegrationsList', () => {
|
|||
});
|
||||
|
||||
it('should track alert list page views', () => {
|
||||
const { category, action } = trackAlertIntergrationsViewsOptions;
|
||||
const { category, action } = trackAlertIntegrationsViewsOptions;
|
||||
expect(Tracking.event).toHaveBeenCalledWith(category, action);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,59 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { GlForm, GlFormSelect, GlCollapse, GlFormInput } from '@gitlab/ui';
|
||||
import AlertsSettingsForm from '~/alerts_settings/components/alerts_settings_form_new.vue';
|
||||
import { defaultAlertSettingsConfig } from './util';
|
||||
|
||||
jest.mock('~/alerts_settings/services');
|
||||
|
||||
describe('AlertsSettingsFormNew', () => {
|
||||
let wrapper;
|
||||
|
||||
const createComponent = ({ methods } = {}, data) => {
|
||||
wrapper = shallowMount(AlertsSettingsForm, {
|
||||
data() {
|
||||
return { ...data };
|
||||
},
|
||||
provide: {
|
||||
...defaultAlertSettingsConfig,
|
||||
},
|
||||
methods,
|
||||
stubs: { GlCollapse, GlFormInput },
|
||||
});
|
||||
};
|
||||
|
||||
const findForm = () => wrapper.find(GlForm);
|
||||
const findSelect = () => wrapper.find(GlFormSelect);
|
||||
const findFormSteps = () => wrapper.find(GlCollapse);
|
||||
const findFormName = () => wrapper.find(GlFormInput);
|
||||
|
||||
afterEach(() => {
|
||||
if (wrapper) {
|
||||
wrapper.destroy();
|
||||
wrapper = null;
|
||||
}
|
||||
});
|
||||
|
||||
describe('with default values', () => {
|
||||
beforeEach(() => {
|
||||
createComponent();
|
||||
});
|
||||
|
||||
it('renders the initial template', () => {
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('render the initial form with only an integration type dropdown', () => {
|
||||
expect(findForm().exists()).toBe(true);
|
||||
expect(findSelect().exists()).toBe(true);
|
||||
expect(findFormSteps().attributes('visible')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('shows the rest of the form when the dropdown is used', async () => {
|
||||
findSelect().vm.$emit('change', 'prometheus');
|
||||
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
expect(findFormName().isVisible()).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,19 +1,13 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { GlModal, GlAlert } from '@gitlab/ui';
|
||||
import AlertsSettingsForm from '~/alerts_settings/components/alerts_settings_form.vue';
|
||||
import IntegrationsList from '~/alerts_settings/components/alerts_integrations_list.vue';
|
||||
import AlertsSettingsForm from '~/alerts_settings/components/alerts_settings_form_old.vue';
|
||||
import ToggleButton from '~/vue_shared/components/toggle_button.vue';
|
||||
import { i18n } from '~/alerts_settings/constants';
|
||||
import service from '~/alerts_settings/services';
|
||||
import { defaultAlertSettingsConfig } from './util';
|
||||
|
||||
jest.mock('~/alerts_settings/services');
|
||||
|
||||
const PROMETHEUS_URL = '/prometheus/alerts/notify.json';
|
||||
const GENERIC_URL = '/alerts/notify.json';
|
||||
const KEY = 'abcedfg123';
|
||||
const INVALID_URL = 'http://invalid';
|
||||
const ACTIVATED = false;
|
||||
|
||||
describe('AlertsSettingsForm', () => {
|
||||
let wrapper;
|
||||
|
||||
|
@ -23,26 +17,7 @@ describe('AlertsSettingsForm', () => {
|
|||
return { ...data };
|
||||
},
|
||||
provide: {
|
||||
generic: {
|
||||
authorizationKey: KEY,
|
||||
formPath: INVALID_URL,
|
||||
url: GENERIC_URL,
|
||||
alertsSetupUrl: INVALID_URL,
|
||||
alertsUsageUrl: INVALID_URL,
|
||||
activated: ACTIVATED,
|
||||
},
|
||||
prometheus: {
|
||||
authorizationKey: KEY,
|
||||
prometheusFormPath: INVALID_URL,
|
||||
prometheusUrl: PROMETHEUS_URL,
|
||||
activated: ACTIVATED,
|
||||
},
|
||||
opsgenie: {
|
||||
opsgenieMvcIsAvailable: true,
|
||||
formPath: INVALID_URL,
|
||||
activated: ACTIVATED,
|
||||
opsgenieMvcTargetUrl: GENERIC_URL,
|
||||
},
|
||||
...defaultAlertSettingsConfig,
|
||||
},
|
||||
methods,
|
||||
});
|
||||
|
@ -63,7 +38,10 @@ describe('AlertsSettingsForm', () => {
|
|||
});
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
if (wrapper) {
|
||||
wrapper.destroy();
|
||||
wrapper = null;
|
||||
}
|
||||
});
|
||||
|
||||
describe('with default values', () => {
|
||||
|
@ -76,11 +54,6 @@ describe('AlertsSettingsForm', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('renders alerts integrations list', () => {
|
||||
createComponent();
|
||||
expect(wrapper.find(IntegrationsList).exists()).toBe(true);
|
||||
});
|
||||
|
||||
describe('reset key', () => {
|
||||
it('triggers resetKey method', () => {
|
||||
const resetKey = jest.fn();
|
||||
|
@ -140,7 +113,7 @@ describe('AlertsSettingsForm', () => {
|
|||
createComponent(
|
||||
{},
|
||||
{
|
||||
selectedEndpoint: 'prometheus',
|
||||
selectedIntegration: 'prometheus',
|
||||
},
|
||||
);
|
||||
});
|
||||
|
@ -154,7 +127,9 @@ describe('AlertsSettingsForm', () => {
|
|||
});
|
||||
|
||||
it('shows the correct default API URL', () => {
|
||||
expect(findUrl().attributes('value')).toBe(PROMETHEUS_URL);
|
||||
expect(findUrl().attributes('value')).toBe(
|
||||
defaultAlertSettingsConfig.prometheus.prometheusUrl,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -163,7 +138,7 @@ describe('AlertsSettingsForm', () => {
|
|||
createComponent(
|
||||
{},
|
||||
{
|
||||
selectedEndpoint: 'opsgenie',
|
||||
selectedIntegration: 'opsgenie',
|
||||
},
|
||||
);
|
||||
});
|
|
@ -0,0 +1,48 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import AlertsSettingsWrapper from '~/alerts_settings/components/alerts_settings_wrapper.vue';
|
||||
import AlertsSettingsFormOld from '~/alerts_settings/components/alerts_settings_form_old.vue';
|
||||
import AlertsSettingsFormNew from '~/alerts_settings/components/alerts_settings_form_new.vue';
|
||||
import IntegrationsList from '~/alerts_settings/components/alerts_integrations_list.vue';
|
||||
import { defaultAlertSettingsConfig } from './util';
|
||||
|
||||
jest.mock('~/alerts_settings/services');
|
||||
|
||||
describe('AlertsSettingsFormWrapper', () => {
|
||||
let wrapper;
|
||||
|
||||
const createComponent = (data = {}, provide = {}) => {
|
||||
wrapper = shallowMount(AlertsSettingsWrapper, {
|
||||
data() {
|
||||
return { ...data };
|
||||
},
|
||||
provide: {
|
||||
...defaultAlertSettingsConfig,
|
||||
glFeatures: { httpIntegrationsList: false },
|
||||
...provide,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
if (wrapper) {
|
||||
wrapper.destroy();
|
||||
wrapper = null;
|
||||
}
|
||||
});
|
||||
|
||||
describe('with default values', () => {
|
||||
it('renders alerts integrations list and old form by default', () => {
|
||||
createComponent();
|
||||
expect(wrapper.find(IntegrationsList).exists()).toBe(true);
|
||||
expect(wrapper.find(AlertsSettingsFormOld).exists()).toBe(true);
|
||||
expect(wrapper.find(AlertsSettingsFormNew).exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('renders alerts integrations list and new form when httpIntegrationsList feature flag is enabled', () => {
|
||||
createComponent({}, { glFeatures: { httpIntegrationsList: true } });
|
||||
expect(wrapper.find(IntegrationsList).exists()).toBe(true);
|
||||
expect(wrapper.find(AlertsSettingsFormOld).exists()).toBe(false);
|
||||
expect(wrapper.find(AlertsSettingsFormNew).exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
28
spec/frontend/alerts_settings/util.js
Normal file
28
spec/frontend/alerts_settings/util.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
const PROMETHEUS_URL = '/prometheus/alerts/notify.json';
|
||||
const GENERIC_URL = '/alerts/notify.json';
|
||||
const KEY = 'abcedfg123';
|
||||
const INVALID_URL = 'http://invalid';
|
||||
const ACTIVATED = false;
|
||||
|
||||
export const defaultAlertSettingsConfig = {
|
||||
generic: {
|
||||
authorizationKey: KEY,
|
||||
formPath: INVALID_URL,
|
||||
url: GENERIC_URL,
|
||||
alertsSetupUrl: INVALID_URL,
|
||||
alertsUsageUrl: INVALID_URL,
|
||||
activated: ACTIVATED,
|
||||
},
|
||||
prometheus: {
|
||||
authorizationKey: KEY,
|
||||
prometheusFormPath: INVALID_URL,
|
||||
prometheusUrl: PROMETHEUS_URL,
|
||||
activated: ACTIVATED,
|
||||
},
|
||||
opsgenie: {
|
||||
opsgenieMvcIsAvailable: true,
|
||||
formPath: INVALID_URL,
|
||||
activated: ACTIVATED,
|
||||
opsgenieMvcTargetUrl: GENERIC_URL,
|
||||
},
|
||||
};
|
|
@ -0,0 +1,42 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Resolvers::AlertManagement::IntegrationsResolver do
|
||||
include GraphqlHelpers
|
||||
|
||||
let_it_be(:current_user) { create(:user) }
|
||||
let_it_be(:project) { create(:project) }
|
||||
let_it_be(:prometheus_integration) { create(:prometheus_service, project: project) }
|
||||
let_it_be(:active_http_integration) { create(:alert_management_http_integration, project: project) }
|
||||
let_it_be(:inactive_http_integration) { create(:alert_management_http_integration, :inactive, project: project) }
|
||||
let_it_be(:other_proj_integration) { create(:alert_management_http_integration) }
|
||||
|
||||
subject { sync(resolve_http_integrations) }
|
||||
|
||||
context 'user does not have permission' do
|
||||
it { is_expected.to be_empty }
|
||||
end
|
||||
|
||||
context 'user has permission' do
|
||||
before do
|
||||
project.add_maintainer(current_user)
|
||||
end
|
||||
|
||||
it { is_expected.to contain_exactly(active_http_integration, prometheus_integration) }
|
||||
|
||||
context 'feature flag is not enabled' do
|
||||
before do
|
||||
stub_feature_flags(multiple_http_integrations: false)
|
||||
end
|
||||
|
||||
it { is_expected.to be_empty }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def resolve_http_integrations(args = {}, context = { current_user: current_user })
|
||||
resolve(described_class, obj: project, ctx: context)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe GitlabSchema.types['AlertManagementHttpIntegration'] do
|
||||
specify { expect(described_class.graphql_name).to eq('AlertManagementHttpIntegration') }
|
||||
|
||||
specify { expect(described_class).to require_graphql_authorizations(:admin_operations) }
|
||||
end
|
|
@ -0,0 +1,22 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe GitlabSchema.types['AlertManagementIntegrationType'] do
|
||||
specify { expect(described_class.graphql_name).to eq('AlertManagementIntegrationType') }
|
||||
|
||||
describe 'statuses' do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
where(:name, :value) do
|
||||
'PROMETHEUS' | :prometheus
|
||||
'HTTP' | :http
|
||||
end
|
||||
|
||||
with_them do
|
||||
it 'exposes a type with the correct value' do
|
||||
expect(described_class.values[name].value).to eq(value)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
21
spec/graphql/types/alert_management/integration_type_spec.rb
Normal file
21
spec/graphql/types/alert_management/integration_type_spec.rb
Normal file
|
@ -0,0 +1,21 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe GitlabSchema.types['AlertManagementIntegration'] do
|
||||
specify { expect(described_class.graphql_name).to eq('AlertManagementIntegration') }
|
||||
|
||||
it 'exposes the expected fields' do
|
||||
expected_fields = %i[
|
||||
id
|
||||
type
|
||||
name
|
||||
active
|
||||
token
|
||||
url
|
||||
api_url
|
||||
]
|
||||
|
||||
expect(described_class).to have_graphql_fields(*expected_fields)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,60 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe GitlabSchema.types['AlertManagementPrometheusIntegration'] do
|
||||
include GraphqlHelpers
|
||||
|
||||
specify { expect(described_class.graphql_name).to eq('AlertManagementPrometheusIntegration') }
|
||||
specify { expect(described_class).to require_graphql_authorizations(:admin_project) }
|
||||
|
||||
describe 'resolvers' do
|
||||
shared_examples_for 'has field with value' do |field_name|
|
||||
it 'correctly renders the field' do
|
||||
expect(resolve_field(field_name, integration)).to eq(value)
|
||||
end
|
||||
end
|
||||
|
||||
let_it_be_with_reload(:integration) { create(:prometheus_service) }
|
||||
|
||||
it_behaves_like 'has field with value', 'name' do
|
||||
let(:value) { integration.title }
|
||||
end
|
||||
|
||||
it_behaves_like 'has field with value', 'type' do
|
||||
let(:value) { :prometheus }
|
||||
end
|
||||
|
||||
it_behaves_like 'has field with value', 'token' do
|
||||
let(:value) { nil }
|
||||
end
|
||||
|
||||
it_behaves_like 'has field with value', 'url' do
|
||||
let(:value) { "http://localhost/#{integration.project.full_path}/prometheus/alerts/notify.json" }
|
||||
end
|
||||
|
||||
it_behaves_like 'has field with value', 'active' do
|
||||
let(:value) { integration.manual_configuration? }
|
||||
end
|
||||
|
||||
context 'with alerting setting' do
|
||||
let_it_be(:alerting_setting) { create(:project_alerting_setting, project: integration.project) }
|
||||
|
||||
it_behaves_like 'has field with value', 'token' do
|
||||
let(:value) { alerting_setting.token }
|
||||
end
|
||||
end
|
||||
|
||||
context 'without project' do
|
||||
let_it_be(:integration) { create(:prometheus_service, project: nil, group: create(:group)) }
|
||||
|
||||
it_behaves_like 'has field with value', 'token' do
|
||||
let(:value) { nil }
|
||||
end
|
||||
|
||||
it_behaves_like 'has field with value', 'url' do
|
||||
let(:value) { nil }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -27,7 +27,8 @@ RSpec.describe GitlabSchema.types['Project'] do
|
|||
environment boards jira_import_status jira_imports services releases release
|
||||
alert_management_alerts alert_management_alert alert_management_alert_status_counts
|
||||
container_expiration_policy service_desk_enabled service_desk_address
|
||||
issue_status_counts terraform_states
|
||||
issue_status_counts terraform_states alert_management_integrations
|
||||
|
||||
]
|
||||
|
||||
expect(described_class).to include_graphql_fields(*expected_fields)
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe AlertManagement::HttpIntegrationPolicy, :models do
|
||||
let(:integration) { create(:alert_management_http_integration) }
|
||||
let(:project) { integration.project }
|
||||
let(:user) { create(:user) }
|
||||
|
||||
subject(:policy) { described_class.new(user, integration) }
|
||||
|
||||
describe 'rules' do
|
||||
it { is_expected.to be_disallowed :admin_operations }
|
||||
|
||||
context 'when maintainer' do
|
||||
before do
|
||||
project.add_maintainer(user)
|
||||
end
|
||||
|
||||
it { is_expected.to be_allowed :admin_operations }
|
||||
end
|
||||
end
|
||||
end
|
23
spec/policies/prometheus_service_policy_spec.rb
Normal file
23
spec/policies/prometheus_service_policy_spec.rb
Normal file
|
@ -0,0 +1,23 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe PrometheusServicePolicy, :models do
|
||||
let(:integration) { create(:prometheus_service) }
|
||||
let(:project) { integration.project }
|
||||
let(:user) { create(:user) }
|
||||
|
||||
subject(:policy) { described_class.new(user, integration) }
|
||||
|
||||
describe 'rules' do
|
||||
it { is_expected.to be_disallowed :admin_project }
|
||||
|
||||
context 'when maintainer' do
|
||||
before do
|
||||
project.add_maintainer(user)
|
||||
end
|
||||
|
||||
it { is_expected.to be_allowed :admin_project }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,83 @@
|
|||
# frozen_string_literal: true
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'getting Alert Management Integrations' do
|
||||
include ::Gitlab::Routing
|
||||
include GraphqlHelpers
|
||||
|
||||
let_it_be(:project) { create(:project, :repository) }
|
||||
let_it_be(:current_user) { create(:user) }
|
||||
let_it_be(:prometheus_service) { create(:prometheus_service, project: project) }
|
||||
let_it_be(:project_alerting_setting) { create(:project_alerting_setting, project: project) }
|
||||
let_it_be(:active_http_integration) { create(:alert_management_http_integration, project: project) }
|
||||
let_it_be(:inactive_http_integration) { create(:alert_management_http_integration, :inactive, project: project) }
|
||||
let_it_be(:other_project_http_integration) { create(:alert_management_http_integration) }
|
||||
|
||||
let(:fields) do
|
||||
<<~QUERY
|
||||
nodes {
|
||||
#{all_graphql_fields_for('AlertManagementIntegration')}
|
||||
}
|
||||
QUERY
|
||||
end
|
||||
|
||||
let(:query) do
|
||||
graphql_query_for(
|
||||
'project',
|
||||
{ 'fullPath' => project.full_path },
|
||||
query_graphql_field('alertManagementIntegrations', {}, fields)
|
||||
)
|
||||
end
|
||||
|
||||
context 'with integrations' do
|
||||
let(:integrations) { graphql_data.dig('project', 'alertManagementIntegrations', 'nodes') }
|
||||
|
||||
context 'without project permissions' do
|
||||
let(:user) { create(:user) }
|
||||
|
||||
before do
|
||||
post_graphql(query, current_user: current_user)
|
||||
end
|
||||
|
||||
it_behaves_like 'a working graphql query'
|
||||
|
||||
it { expect(integrations).to be_nil }
|
||||
end
|
||||
|
||||
context 'with project permissions' do
|
||||
before do
|
||||
project.add_maintainer(current_user)
|
||||
post_graphql(query, current_user: current_user)
|
||||
end
|
||||
|
||||
let(:http_integration) { integrations.first }
|
||||
let(:prometheus_integration) { integrations.second }
|
||||
|
||||
it_behaves_like 'a working graphql query'
|
||||
|
||||
it { expect(integrations.size).to eq(2) }
|
||||
|
||||
it 'returns the correct properties of the integrations' do
|
||||
expect(http_integration).to include(
|
||||
'id' => GitlabSchema.id_from_object(active_http_integration).to_s,
|
||||
'type' => 'HTTP',
|
||||
'name' => active_http_integration.name,
|
||||
'active' => active_http_integration.active,
|
||||
'token' => active_http_integration.token,
|
||||
'url' => active_http_integration.url,
|
||||
'apiUrl' => nil
|
||||
)
|
||||
|
||||
expect(prometheus_integration).to include(
|
||||
'id' => GitlabSchema.id_from_object(prometheus_service).to_s,
|
||||
'type' => 'PROMETHEUS',
|
||||
'name' => 'Prometheus',
|
||||
'active' => prometheus_service.manual_configuration?,
|
||||
'token' => project_alerting_setting.token,
|
||||
'url' => "http://localhost/#{project.full_path}/prometheus/alerts/notify.json",
|
||||
'apiUrl' => prometheus_service.api_url
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -66,7 +66,20 @@ RSpec.describe 'Robots.txt Requests', :aggregate_failures do
|
|||
'/foo/bar/uploads/foo',
|
||||
'/foo/bar/project_members',
|
||||
'/foo/bar/settings',
|
||||
'/namespace/subnamespace/design.gitlab.com/settings'
|
||||
'/namespace/subnamespace/design.gitlab.com/settings',
|
||||
'/foo/bar/-/import',
|
||||
'/foo/bar/-/environments',
|
||||
'/foo/bar/-/jobs',
|
||||
'/foo/bar/-/requirements_management',
|
||||
'/foo/bar/-/pipelines',
|
||||
'/foo/bar/-/pipeline_schedules',
|
||||
'/foo/bar/-/dependencies',
|
||||
'/foo/bar/-/licenses',
|
||||
'/foo/bar/-/metrics',
|
||||
'/foo/bar/-/incidents',
|
||||
'/foo/bar/-/value_stream_analytics',
|
||||
'/foo/bar/-/analytics',
|
||||
'/foo/bar/insights'
|
||||
]
|
||||
|
||||
requests.each do |request|
|
||||
|
|
Loading…
Reference in a new issue