summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/boards/components/boards_selector.vue2
-rw-r--r--app/assets/javascripts/jobs/components/manual_variables_form.vue8
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard.vue21
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard_header.vue9
-rw-r--r--app/assets/javascripts/monitoring/components/empty_state.vue67
-rw-r--r--app/assets/javascripts/monitoring/components/graph_group.vue17
-rw-r--r--app/assets/javascripts/monitoring/stores/mutation_types.js1
-rw-r--r--app/assets/javascripts/monitoring/stores/mutations.js12
-rw-r--r--app/assets/javascripts/monitoring/stores/state.js7
-rw-r--r--app/assets/javascripts/notes/components/comment_form.vue2
-rw-r--r--app/assets/javascripts/notes/components/note_form.vue2
-rw-r--r--app/assets/javascripts/releases/components/release_block_header.vue2
-rw-r--r--app/assets/javascripts/reports/components/grouped_test_reports_app.vue7
-rw-r--r--app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/lock/edit_form_buttons.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue6
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/project_selector/project_list_item.vue2
-rw-r--r--app/assets/stylesheets/framework/common.scss1
-rw-r--r--app/assets/stylesheets/framework/variables.scss2
-rw-r--r--app/assets/stylesheets/pages/runners.scss3
-rw-r--r--app/graphql/mutations/notes/create/base.rb8
-rw-r--r--app/graphql/mutations/snippets/create.rb4
-rw-r--r--app/graphql/mutations/snippets/update.rb4
-rw-r--r--app/helpers/environments_helper.rb17
-rw-r--r--app/presenters/clusters/cluster_presenter.rb2
-rw-r--r--app/services/concerns/incident_management/settings.rb2
-rw-r--r--app/services/incident_management/pager_duty/create_incident_issue_service.rb72
-rw-r--r--app/services/snippets/base_service.rb16
-rw-r--r--app/services/snippets/create_service.rb6
-rw-r--r--app/services/snippets/update_service.rb8
-rw-r--r--app/views/admin/runners/_runner.html.haml4
-rw-r--r--app/views/ci/group_variables/_index.html.haml4
-rw-r--r--app/views/ci/group_variables/_variable_header.html.haml4
-rw-r--r--app/views/ci/variables/_environment_scope_header.html.haml2
-rw-r--r--app/views/ci/variables/_variable_header.html.haml6
-rw-r--r--app/views/profiles/active_sessions/_active_session.html.haml2
-rw-r--r--app/views/profiles/gpg_keys/_key.html.haml2
-rw-r--r--app/views/profiles/keys/_key.html.haml6
-rw-r--r--app/views/profiles/passwords/edit.html.haml2
-rw-r--r--app/views/profiles/two_factor_auths/_codes.html.haml2
-rw-r--r--app/views/profiles/two_factor_auths/show.html.haml2
-rw-r--r--app/views/projects/blob/_editor.html.haml4
-rw-r--r--app/views/projects/commit/_commit_box.html.haml4
-rw-r--r--app/views/projects/issues/_nav_btns.html.haml2
-rw-r--r--app/views/projects/merge_requests/_discussion.html.haml2
-rw-r--r--app/views/projects/merge_requests/_nav_btns.html.haml2
-rw-r--r--app/views/projects/mirrors/_ssh_host_keys.html.haml2
-rw-r--r--app/views/projects/no_repo.html.haml2
-rw-r--r--app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml4
-rw-r--r--app/views/projects/project_templates/_built_in_templates.html.haml4
-rw-r--r--app/views/projects/project_templates/_project_fields_form.html.haml2
-rw-r--r--app/views/sent_notifications/unsubscribe.html.haml4
-rw-r--r--app/views/shared/groups/_dropdown.html.haml2
-rw-r--r--app/views/shared/issuable/_form.html.haml2
-rw-r--r--app/views/shared/milestones/_deprecation_message.html.haml2
-rw-r--r--app/views/shared/notes/_comment_button.html.haml2
-rw-r--r--app/views/shared/projects/_project.html.haml4
-rw-r--r--app/workers/all_queues.yml16
-rw-r--r--app/workers/incident_management/pager_duty/process_incident_worker.rb42
60 files changed, 305 insertions, 149 deletions
diff --git a/app/assets/javascripts/boards/components/boards_selector.vue b/app/assets/javascripts/boards/components/boards_selector.vue
index 80db9930259..dbe3e0790f6 100644
--- a/app/assets/javascripts/boards/components/boards_selector.vue
+++ b/app/assets/javascripts/boards/components/boards_selector.vue
@@ -233,7 +233,7 @@ export default {
</script>
<template>
- <div class="boards-switcher js-boards-selector append-right-10">
+ <div class="boards-switcher js-boards-selector gl-mr-3">
<span class="boards-selector-wrapper js-boards-selector-wrapper">
<gl-dropdown
data-qa-selector="boards_dropdown"
diff --git a/app/assets/javascripts/jobs/components/manual_variables_form.vue b/app/assets/javascripts/jobs/components/manual_variables_form.vue
index 9163e7a87f1..d83c598dd48 100644
--- a/app/assets/javascripts/jobs/components/manual_variables_form.vue
+++ b/app/assets/javascripts/jobs/components/manual_variables_form.vue
@@ -112,7 +112,7 @@ export default {
<div v-for="variable in variables" :key="variable.id" class="gl-responsive-table-row">
<div class="table-section section-50">
<div class="table-mobile-header" role="rowheader">{{ s__('Pipeline|Key') }}</div>
- <div class="table-mobile-content append-right-10">
+ <div class="table-mobile-content gl-mr-3">
<input
:ref="`${$options.inputTypes.key}-${variable.id}`"
v-model="variable.key"
@@ -124,7 +124,7 @@ export default {
<div class="table-section section-50">
<div class="table-mobile-header" role="rowheader">{{ s__('Pipeline|Value') }}</div>
- <div class="table-mobile-content append-right-10">
+ <div class="table-mobile-content gl-mr-3">
<input
:ref="`${$options.inputTypes.value}-${variable.id}`"
v-model="variable.secret_value"
@@ -149,7 +149,7 @@ export default {
<div class="gl-responsive-table-row">
<div class="table-section section-50">
<div class="table-mobile-header" role="rowheader">{{ s__('Pipeline|Key') }}</div>
- <div class="table-mobile-content append-right-10">
+ <div class="table-mobile-content gl-mr-3">
<input
ref="inputKey"
v-model="key"
@@ -161,7 +161,7 @@ export default {
<div class="table-section section-50">
<div class="table-mobile-header" role="rowheader">{{ s__('Pipeline|Value') }}</div>
- <div class="table-mobile-content append-right-10">
+ <div class="table-mobile-content gl-mr-3">
<input
ref="inputSecretValue"
v-model="secretValue"
diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue
index f685d67751c..bde62275797 100644
--- a/app/assets/javascripts/monitoring/components/dashboard.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard.vue
@@ -161,7 +161,6 @@ export default {
...mapState('monitoringDashboard', [
'dashboard',
'emptyState',
- 'showEmptyState',
'expandedPanel',
'variables',
'links',
@@ -169,6 +168,9 @@ export default {
'hasDashboardValidationWarnings',
]),
...mapGetters('monitoringDashboard', ['selectedDashboard', 'getMetricStates']),
+ shouldShowEmptyState() {
+ return Boolean(this.emptyState);
+ },
shouldShowVariablesSection() {
return Boolean(this.variables.length);
},
@@ -278,6 +280,14 @@ export default {
return null;
},
/**
+ * Return true if the entire group is loading.
+ * @param {String} groupKey - Identifier for group
+ * @returns {boolean}
+ */
+ isGroupLoading(groupKey) {
+ return this.groupSingleEmptyState(groupKey) === metricStates.LOADING;
+ },
+ /**
* A group should be not collapsed if any metric is loaded (OK)
*
* @param {String} groupKey - Identifier for group
@@ -412,9 +422,9 @@ export default {
@dateTimePickerInvalid="onDateTimePickerInvalid"
@setRearrangingPanels="onSetRearrangingPanels"
/>
- <variables-section v-if="shouldShowVariablesSection && !showEmptyState" />
- <links-section v-if="shouldShowLinksSection && !showEmptyState" />
- <div v-if="!showEmptyState">
+ <template v-if="!shouldShowEmptyState">
+ <variables-section v-if="shouldShowVariablesSection" />
+ <links-section v-if="shouldShowLinksSection" />
<dashboard-panel
v-show="expandedPanel.panel"
ref="expandedPanel"
@@ -449,6 +459,7 @@ export default {
:key="`${groupData.group}.${groupData.priority}`"
:name="groupData.group"
:show-panels="showPanels"
+ :is-loading="isGroupLoading(groupData.key)"
:collapse-group="collapseGroup(groupData.key)"
>
<vue-draggable
@@ -506,7 +517,7 @@ export default {
</div>
</graph-group>
</div>
- </div>
+ </template>
<empty-state
v-else
:selected-state="emptyState"
diff --git a/app/assets/javascripts/monitoring/components/dashboard_header.vue b/app/assets/javascripts/monitoring/components/dashboard_header.vue
index 1d929b3b558..ae8c586ff8c 100644
--- a/app/assets/javascripts/monitoring/components/dashboard_header.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard_header.vue
@@ -119,10 +119,10 @@ export default {
},
computed: {
...mapState('monitoringDashboard', [
+ 'emptyState',
'environmentsLoading',
'currentEnvironmentName',
'isUpdatingStarredValue',
- 'showEmptyState',
'dashboardTimezone',
'projectPath',
'canAccessOperationsSettings',
@@ -132,13 +132,16 @@ export default {
isOutOfTheBoxDashboard() {
return this.selectedDashboard?.out_of_the_box_dashboard;
},
+ shouldShowEmptyState() {
+ return Boolean(this.emptyState);
+ },
shouldShowEnvironmentsDropdownNoMatchedMsg() {
return !this.environmentsLoading && this.filteredEnvironments.length === 0;
},
addingMetricsAvailable() {
return (
this.customMetricsAvailable &&
- !this.showEmptyState &&
+ !this.shouldShowEmptyState &&
// Custom metrics only avaialble on system dashboards because
// they are stored in the database. This can be improved. See:
// https://gitlab.com/gitlab-org/gitlab/-/issues/28241
@@ -146,7 +149,7 @@ export default {
);
},
showRearrangePanelsBtn() {
- return !this.showEmptyState && this.rearrangePanelsAvailable;
+ return !this.shouldShowEmptyState && this.rearrangePanelsAvailable;
},
displayUtc() {
return this.dashboardTimezone === timezones.UTC;
diff --git a/app/assets/javascripts/monitoring/components/empty_state.vue b/app/assets/javascripts/monitoring/components/empty_state.vue
index 000420e2662..5e7c9b5d906 100644
--- a/app/assets/javascripts/monitoring/components/empty_state.vue
+++ b/app/assets/javascripts/monitoring/components/empty_state.vue
@@ -1,13 +1,19 @@
<script>
-import { GlEmptyState } from '@gitlab/ui';
+import { GlLoadingIcon, GlEmptyState } from '@gitlab/ui';
import { __ } from '~/locale';
import { dashboardEmptyStates } from '../constants';
export default {
components: {
+ GlLoadingIcon,
GlEmptyState,
},
props: {
+ selectedState: {
+ type: String,
+ required: true,
+ validator: state => Object.values(dashboardEmptyStates).includes(state),
+ },
documentationPath: {
type: String,
required: true,
@@ -22,10 +28,6 @@ export default {
required: false,
default: '',
},
- selectedState: {
- type: String,
- required: true,
- },
emptyGettingStartedSvgPath: {
type: String,
required: true,
@@ -54,52 +56,49 @@ export default {
},
data() {
return {
+ /**
+ * Possible empty states.
+ * Keys in each state must match GlEmptyState props
+ */
states: {
[dashboardEmptyStates.GETTING_STARTED]: {
- svgUrl: this.emptyGettingStartedSvgPath,
+ svgPath: this.emptyGettingStartedSvgPath,
title: __('Get started with performance monitoring'),
description: __(`Stay updated about the performance and health
of your environment by configuring Prometheus to monitor your deployments.`),
- buttonText: __('Install on clusters'),
- buttonPath: this.clustersPath,
+ primaryButtonText: __('Install on clusters'),
+ primaryButtonLink: this.clustersPath,
secondaryButtonText: __('Configure existing installation'),
- secondaryButtonPath: this.settingsPath,
- },
- [dashboardEmptyStates.LOADING]: {
- svgUrl: this.emptyLoadingSvgPath,
- title: __('Waiting for performance data'),
- description: __(`Creating graphs uses the data from the Prometheus server.
- If this takes a long time, ensure that data is available.`),
- buttonText: __('View documentation'),
- buttonPath: this.documentationPath,
- secondaryButtonText: '',
- secondaryButtonPath: '',
+ secondaryButtonLink: this.settingsPath,
},
[dashboardEmptyStates.NO_DATA]: {
- svgUrl: this.emptyNoDataSvgPath,
+ svgPath: this.emptyNoDataSvgPath,
title: __('No data found'),
description: __(`You are connected to the Prometheus server, but there is currently
no data to display.`),
- buttonText: __('Configure Prometheus'),
- buttonPath: this.settingsPath,
+ primaryButtonText: __('Configure Prometheus'),
+ primaryButtonLink: this.settingsPath,
secondaryButtonText: '',
- secondaryButtonPath: '',
+ secondaryButtonLink: '',
},
[dashboardEmptyStates.UNABLE_TO_CONNECT]: {
- svgUrl: this.emptyUnableToConnectSvgPath,
+ svgPath: this.emptyUnableToConnectSvgPath,
title: __('Unable to connect to Prometheus server'),
description: __(
'Ensure connectivity is available from the GitLab server to the Prometheus server',
),
- buttonText: __('View documentation'),
- buttonPath: this.documentationPath,
+ primaryButtonText: __('View documentation'),
+ primaryButtonLink: this.documentationPath,
secondaryButtonText: __('Configure Prometheus'),
- secondaryButtonPath: this.settingsPath,
+ secondaryButtonLink: this.settingsPath,
},
},
};
},
computed: {
+ isLoading() {
+ return this.selectedState === dashboardEmptyStates.LOADING;
+ },
currentState() {
return this.states[this.selectedState];
},
@@ -108,14 +107,8 @@ export default {
</script>
<template>
- <gl-empty-state
- :title="currentState.title"
- :description="currentState.description"
- :primary-button-text="currentState.buttonText"
- :primary-button-link="currentState.buttonPath"
- :secondary-button-text="currentState.secondaryButtonText"
- :secondary-button-link="currentState.secondaryButtonPath"
- :svg-path="currentState.svgUrl"
- :compact="compact"
- />
+ <div>
+ <gl-loading-icon v-if="isLoading" size="xl" class="gl-my-9" />
+ <gl-empty-state v-if="currentState" v-bind="currentState" :compact="compact" />
+ </div>
</template>
diff --git a/app/assets/javascripts/monitoring/components/graph_group.vue b/app/assets/javascripts/monitoring/components/graph_group.vue
index 2d3a839d826..ecb8ef4a0d0 100644
--- a/app/assets/javascripts/monitoring/components/graph_group.vue
+++ b/app/assets/javascripts/monitoring/components/graph_group.vue
@@ -1,9 +1,10 @@
<script>
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
export default {
components: {
- Icon,
+ GlLoadingIcon,
+ GlIcon,
},
props: {
name: {
@@ -15,6 +16,11 @@ export default {
required: false,
default: true,
},
+ isLoading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
/**
* Initial value of collapse on mount.
*/
@@ -55,15 +61,18 @@ export default {
<div v-if="showPanels" ref="graph-group" class="card prometheus-panel">
<div class="card-header d-flex align-items-center">
<h4 class="flex-grow-1">{{ name }}</h4>
+ <gl-loading-icon v-if="isLoading" name="loading" />
<a
data-testid="group-toggle-button"
+ :aria-label="__('Toggle collapse')"
+ :icon="caretIcon"
role="button"
- class="js-graph-group-toggle gl-text-gray-900"
+ class="js-graph-group-toggle gl-display-flex gl-ml-2 gl-text-gray-900"
tabindex="0"
@click="collapse"
@keyup.enter="collapse"
>
- <icon :size="16" :aria-label="__('Toggle collapse')" :name="caretIcon" />
+ <gl-icon :name="caretIcon" />
</a>
</div>
<div
diff --git a/app/assets/javascripts/monitoring/stores/mutation_types.js b/app/assets/javascripts/monitoring/stores/mutation_types.js
index 72b48c251ae..e1fa037c5bb 100644
--- a/app/assets/javascripts/monitoring/stores/mutation_types.js
+++ b/app/assets/javascripts/monitoring/stores/mutation_types.js
@@ -40,7 +40,6 @@ export const SET_ALL_DASHBOARDS = 'SET_ALL_DASHBOARDS';
export const SET_ENDPOINTS = 'SET_ENDPOINTS';
export const SET_INITIAL_STATE = 'SET_INITIAL_STATE';
export const SET_GETTING_STARTED_EMPTY_STATE = 'SET_GETTING_STARTED_EMPTY_STATE';
-export const SET_NO_DATA_EMPTY_STATE = 'SET_NO_DATA_EMPTY_STATE';
export const SET_SHOW_ERROR_BANNER = 'SET_SHOW_ERROR_BANNER';
export const SET_PANEL_GROUP_METRICS = 'SET_PANEL_GROUP_METRICS';
export const SET_ENVIRONMENTS_FILTER = 'SET_ENVIRONMENTS_FILTER';
diff --git a/app/assets/javascripts/monitoring/stores/mutations.js b/app/assets/javascripts/monitoring/stores/mutations.js
index 73d95f6638d..28c6b14a029 100644
--- a/app/assets/javascripts/monitoring/stores/mutations.js
+++ b/app/assets/javascripts/monitoring/stores/mutations.js
@@ -59,7 +59,6 @@ export default {
*/
[types.REQUEST_METRICS_DASHBOARD](state) {
state.emptyState = dashboardEmptyStates.LOADING;
- state.showEmptyState = true;
},
[types.RECEIVE_METRICS_DASHBOARD_SUCCESS](state, dashboardYML) {
const { dashboard, panelGroups, variables, links } = mapToDashboardViewModel(dashboardYML);
@@ -72,13 +71,14 @@ export default {
if (!state.dashboard.panelGroups.length) {
state.emptyState = dashboardEmptyStates.NO_DATA;
+ } else {
+ state.emptyState = null;
}
},
[types.RECEIVE_METRICS_DASHBOARD_FAILURE](state, error) {
state.emptyState = error
? dashboardEmptyStates.UNABLE_TO_CONNECT
: dashboardEmptyStates.NO_DATA;
- state.showEmptyState = true;
},
[types.REQUEST_DASHBOARD_STARRING](state) {
@@ -152,9 +152,6 @@ export default {
const metric = findMetricInDashboard(metricId, state.dashboard);
metric.loading = false;
- state.showEmptyState = false;
- state.emptyState = null;
-
if (!data.result || data.result.length === 0) {
metric.state = metricStates.NO_DATA;
metric.result = null;
@@ -184,13 +181,8 @@ export default {
state.timeRange = timeRange;
},
[types.SET_GETTING_STARTED_EMPTY_STATE](state) {
- state.showEmptyState = true;
state.emptyState = dashboardEmptyStates.GETTING_STARTED;
},
- [types.SET_NO_DATA_EMPTY_STATE](state) {
- state.showEmptyState = true;
- state.emptyState = dashboardEmptyStates.NO_DATA;
- },
[types.SET_ALL_DASHBOARDS](state, dashboards) {
state.allDashboards = dashboards || [];
},
diff --git a/app/assets/javascripts/monitoring/stores/state.js b/app/assets/javascripts/monitoring/stores/state.js
index a7f07234287..89738756ffe 100644
--- a/app/assets/javascripts/monitoring/stores/state.js
+++ b/app/assets/javascripts/monitoring/stores/state.js
@@ -21,8 +21,13 @@ export default () => ({
// Dashboard data
hasDashboardValidationWarnings: false,
+
+ /**
+ * {?String} If set, dashboard should display a global
+ * empty state, there is no way to interact (yet)
+ * with the dashboard.
+ */
emptyState: dashboardEmptyStates.GETTING_STARTED,
- showEmptyState: true,
showErrorBanner: true,
isUpdatingStarredValue: false,
dashboard: {
diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue
index 679b81ce583..ac93d3df654 100644
--- a/app/assets/javascripts/notes/components/comment_form.vue
+++ b/app/assets/javascripts/notes/components/comment_form.vue
@@ -419,7 +419,7 @@ export default {
</gl-alert>
<div class="note-form-actions">
<div
- class="btn-group append-right-10 comment-type-dropdown js-comment-type-dropdown droplab-dropdown"
+ class="btn-group gl-mr-3 comment-type-dropdown js-comment-type-dropdown droplab-dropdown"
>
<button
:disabled="isSubmitButtonDisabled"
diff --git a/app/assets/javascripts/notes/components/note_form.vue b/app/assets/javascripts/notes/components/note_form.vue
index f0c3bd9d874..24227d55ebf 100644
--- a/app/assets/javascripts/notes/components/note_form.vue
+++ b/app/assets/javascripts/notes/components/note_form.vue
@@ -410,7 +410,7 @@ export default {
</button>
<button
v-if="discussion.resolvable"
- class="btn btn-nr btn-default append-right-10 js-comment-resolve-button"
+ class="btn btn-nr btn-default gl-mr-3 js-comment-resolve-button"
@click.prevent="handleUpdate(true)"
>
{{ resolveButtonTitle }}
diff --git a/app/assets/javascripts/releases/components/release_block_header.vue b/app/assets/javascripts/releases/components/release_block_header.vue
index ed49841757a..310fba0fe76 100644
--- a/app/assets/javascripts/releases/components/release_block_header.vue
+++ b/app/assets/javascripts/releases/components/release_block_header.vue
@@ -56,7 +56,7 @@ export default {
v-gl-tooltip
category="primary"
variant="default"
- class="append-right-10 js-edit-button ml-2 pb-2"
+ class="gl-mr-3 js-edit-button ml-2 pb-2"
:title="__('Edit this release')"
:href="editLink"
>
diff --git a/app/assets/javascripts/reports/components/grouped_test_reports_app.vue b/app/assets/javascripts/reports/components/grouped_test_reports_app.vue
index b28a847e751..b8a8cb940e7 100644
--- a/app/assets/javascripts/reports/components/grouped_test_reports_app.vue
+++ b/app/assets/javascripts/reports/components/grouped_test_reports_app.vue
@@ -114,7 +114,12 @@ export default {
class="mr-widget-section grouped-security-reports mr-report"
>
<template v-if="showViewFullReport" #actionButtons>
- <gl-button :href="testTabURL" icon="external-link" data-testid="group-test-reports-full-link">
+ <gl-button
+ :href="testTabURL"
+ icon="external-link"
+ data-testid="group-test-reports-full-link"
+ class="gl-mr-3"
+ >
{{ s__('ciReport|View full report') }}
</gl-button>
</template>
diff --git a/app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue b/app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue
index 32b142a3346..80928649a03 100644
--- a/app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue
+++ b/app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue
@@ -62,7 +62,7 @@ export default {
<template>
<div class="sidebar-item-warning-message-actions">
- <button type="button" class="btn btn-default append-right-10" @click="closeForm">
+ <button type="button" class="btn btn-default gl-mr-3" @click="closeForm">
{{ __('Cancel') }}
</button>
<button
diff --git a/app/assets/javascripts/sidebar/components/lock/edit_form_buttons.vue b/app/assets/javascripts/sidebar/components/lock/edit_form_buttons.vue
index f88bde624b4..2e85ded8ade 100644
--- a/app/assets/javascripts/sidebar/components/lock/edit_form_buttons.vue
+++ b/app/assets/javascripts/sidebar/components/lock/edit_form_buttons.vue
@@ -41,7 +41,7 @@ export default {
<template>
<div class="sidebar-item-warning-message-actions">
- <button type="button" class="btn btn-default append-right-10" @click="closeForm">
+ <button type="button" class="btn btn-default gl-mr-3" @click="closeForm">
{{ __('Cancel') }}
</button>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue
index 92848e86e76..f02e0ac84da 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue
@@ -87,7 +87,7 @@ export default {
<status-icon status="success" />
<div class="media-body">
<h4 class="d-flex align-items-start">
- <span class="append-right-10">
+ <span class="gl-mr-3">
<span class="js-status-text-before-author">{{ statusTextBeforeAuthor }}</span>
<mr-widget-author :author="mr.setToAutoMergeBy" />
<span class="js-status-text-after-author">{{ statusTextAfterAuthor }}</span>
@@ -113,9 +113,7 @@ export default {
{{ s__('mrWidget|The source branch will be deleted') }}
</p>
<p v-else class="d-flex align-items-start">
- <span class="append-right-10">{{
- s__('mrWidget|The source branch will not be deleted')
- }}</span>
+ <span class="gl-mr-3">{{ s__('mrWidget|The source branch will not be deleted') }}</span>
<a
v-if="canRemoveSourceBranch"
:disabled="isRemovingSourceBranch"
diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
index a28936456ff..fdcbcdce51b 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
@@ -384,7 +384,7 @@ export default {
v-if="mr.testResultsPath"
class="js-reports-container"
:endpoint="mr.testResultsPath"
- :pipeline-path="mr.mergeRequestAddCiConfigPath"
+ :pipeline-path="mr.pipeline.path"
/>
<terraform-plan v-if="mr.terraformReportsPath" :endpoint="mr.terraformReportsPath" />
diff --git a/app/assets/javascripts/vue_shared/components/project_selector/project_list_item.vue b/app/assets/javascripts/vue_shared/components/project_selector/project_list_item.vue
index 1cee800de44..8c6d795f4a6 100644
--- a/app/assets/javascripts/vue_shared/components/project_selector/project_list_item.vue
+++ b/app/assets/javascripts/vue_shared/components/project_selector/project_list_item.vue
@@ -56,7 +56,7 @@ export default {
@click="onClick"
>
<icon
- class="prepend-left-10 append-right-10 flex-shrink-0 position-top-0 js-selected-icon"
+ class="prepend-left-10 gl-mr-3 flex-shrink-0 position-top-0 js-selected-icon"
:class="{ 'js-selected visible': selected, 'js-unselected invisible': !selected }"
name="mobile-issue-close"
/>
diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss
index fe48381d9c3..f2ff8b74790 100644
--- a/app/assets/stylesheets/framework/common.scss
+++ b/app/assets/stylesheets/framework/common.scss
@@ -404,7 +404,6 @@ img.emoji {
.prepend-left-15 { margin-left: 15px; }
.prepend-left-20 { margin-left: 20px; }
.prepend-left-64 { margin-left: 64px; }
-.append-right-10 { margin-right: 10px; }
.append-right-15 { margin-right: 15px; }
.append-right-20 { margin-right: 20px; }
.append-bottom-10 { margin-bottom: 10px; }
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index 79f9cf5941f..265dceb3c61 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -171,7 +171,7 @@ $gray-500: #a7a7a7 !default;
$gray-600: #919191 !default;
$gray-700: #707070 !default;
$gray-800: #4f4f4f !default;
-$gray-900: #2e2e2e !default;
+$gray-900: #303030 !default;
$gray-950: #1f1f1f !default;
$greens: (
diff --git a/app/assets/stylesheets/pages/runners.scss b/app/assets/stylesheets/pages/runners.scss
index dc3811bab65..66d2f76c558 100644
--- a/app/assets/stylesheets/pages/runners.scss
+++ b/app/assets/stylesheets/pages/runners.scss
@@ -45,8 +45,7 @@
color: $gl-text-color-secondary;
}
- .fa-pause,
- .fa-play {
+ .fa-pause {
font-size: 11px;
}
}
diff --git a/app/graphql/mutations/notes/create/base.rb b/app/graphql/mutations/notes/create/base.rb
index cf9f74a63d8..f081eac368e 100644
--- a/app/graphql/mutations/notes/create/base.rb
+++ b/app/graphql/mutations/notes/create/base.rb
@@ -18,6 +18,11 @@ module Mutations
required: true,
description: copy_field_description(Types::Notes::NoteType, :body)
+ argument :confidential,
+ GraphQL::BOOLEAN_TYPE,
+ required: false,
+ description: 'The confidentiality flag of a note. Default is false.'
+
def resolve(args)
noteable = authorized_find!(id: args[:noteable_id])
@@ -40,7 +45,8 @@ module Mutations
def create_note_params(noteable, args)
{
noteable: noteable,
- note: args[:body]
+ note: args[:body],
+ confidential: args[:confidential]
}
end
end
diff --git a/app/graphql/mutations/snippets/create.rb b/app/graphql/mutations/snippets/create.rb
index 1545fd70290..89c21486a74 100644
--- a/app/graphql/mutations/snippets/create.rb
+++ b/app/graphql/mutations/snippets/create.rb
@@ -85,9 +85,9 @@ module Mutations
def create_params(args)
args.tap do |create_args|
- # We need to rename `files` into `snippet_files` because
+ # We need to rename `files` into `snippet_actions` because
# it's the expected key param
- create_args[:snippet_files] = create_args.delete(:files)&.map(&:to_h)
+ create_args[:snippet_actions] = create_args.delete(:files)&.map(&:to_h)
# We need to rename `uploaded_files` into `files` because
# it's the expected key param
diff --git a/app/graphql/mutations/snippets/update.rb b/app/graphql/mutations/snippets/update.rb
index f0a22ebaa9d..8890158b0df 100644
--- a/app/graphql/mutations/snippets/update.rb
+++ b/app/graphql/mutations/snippets/update.rb
@@ -56,9 +56,9 @@ module Mutations
def update_params(args)
args.tap do |update_args|
- # We need to rename `files` into `snippet_files` because
+ # We need to rename `files` into `snippet_actions` because
# it's the expected key param
- update_args[:snippet_files] = update_args.delete(:files)&.map(&:to_h)
+ update_args[:snippet_actions] = update_args.delete(:files)&.map(&:to_h)
end
end
end
diff --git a/app/helpers/environments_helper.rb b/app/helpers/environments_helper.rb
index 90ebab731ea..b522a9dfb4f 100644
--- a/app/helpers/environments_helper.rb
+++ b/app/helpers/environments_helper.rb
@@ -24,7 +24,7 @@ module EnvironmentsHelper
def metrics_data(project, environment)
metrics_data = {}
metrics_data.merge!(project_metrics_data(project)) if project
- metrics_data.merge!(environment_metrics_data(environment)) if environment
+ metrics_data.merge!(environment_metrics_data(environment, project)) if environment
metrics_data.merge!(project_and_environment_metrics_data(project, environment)) if project && environment
metrics_data.merge!(static_metrics_data)
@@ -66,11 +66,11 @@ module EnvironmentsHelper
}
end
- def environment_metrics_data(environment)
+ def environment_metrics_data(environment, project = nil)
return {} unless environment
{
- 'metrics-dashboard-base-path' => environment_metrics_path(environment),
+ 'metrics-dashboard-base-path' => metrics_dashboard_base_path(environment, project),
'current-environment-name' => environment.name,
'has-metrics' => "#{environment.has_metrics?}",
'prometheus-status' => "#{environment.prometheus_status}",
@@ -78,6 +78,17 @@ module EnvironmentsHelper
}
end
+ def metrics_dashboard_base_path(environment, project)
+ # This is needed to support our transition from environment scoped metric paths to project scoped.
+ if project
+ path = project_metrics_dashboard_path(project)
+
+ return path if request.path.include?(path)
+ end
+
+ environment_metrics_path(environment)
+ end
+
def project_and_environment_metrics_data(project, environment)
return {} unless project && environment
diff --git a/app/presenters/clusters/cluster_presenter.rb b/app/presenters/clusters/cluster_presenter.rb
index 3dfa9626a79..6185f5cb4e5 100644
--- a/app/presenters/clusters/cluster_presenter.rb
+++ b/app/presenters/clusters/cluster_presenter.rb
@@ -76,9 +76,11 @@ module Clusters
'clusters-path': clusterable.index_path,
'dashboard-endpoint': clusterable.metrics_dashboard_path(cluster),
'documentation-path': help_page_path('user/project/clusters/index', anchor: 'monitoring-your-kubernetes-cluster-ultimate'),
+ 'add-dashboard-documentation-path': help_page_path('user/project/integrations/prometheus.md', anchor: 'adding-a-new-dashboard-to-your-project'),
'empty-getting-started-svg-path': image_path('illustrations/monitoring/getting_started.svg'),
'empty-loading-svg-path': image_path('illustrations/monitoring/loading.svg'),
'empty-no-data-svg-path': image_path('illustrations/monitoring/no_data.svg'),
+ 'empty-no-data-small-svg-path': image_path('illustrations/chart-empty-state-small.svg'),
'empty-unable-to-connect-svg-path': image_path('illustrations/monitoring/unable_to_connect.svg'),
'settings-path': '',
'project-path': '',
diff --git a/app/services/concerns/incident_management/settings.rb b/app/services/concerns/incident_management/settings.rb
index 5f56d6e7f53..491bd4fa6bf 100644
--- a/app/services/concerns/incident_management/settings.rb
+++ b/app/services/concerns/incident_management/settings.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
module IncidentManagement
module Settings
+ include Gitlab::Utils::StrongMemoize
+
def incident_management_setting
strong_memoize(:incident_management_setting) do
project.incident_management_setting ||
diff --git a/app/services/incident_management/pager_duty/create_incident_issue_service.rb b/app/services/incident_management/pager_duty/create_incident_issue_service.rb
new file mode 100644
index 00000000000..ee0feb49e0d
--- /dev/null
+++ b/app/services/incident_management/pager_duty/create_incident_issue_service.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+module IncidentManagement
+ module PagerDuty
+ class CreateIncidentIssueService < BaseService
+ include IncidentManagement::Settings
+
+ def initialize(project, incident_payload)
+ super(project, User.alert_bot, incident_payload)
+ end
+
+ def execute
+ return forbidden unless webhook_available?
+
+ issue = create_issue
+ return error(issue.errors.full_messages.to_sentence, issue) unless issue.valid?
+
+ success(issue)
+ end
+
+ private
+
+ alias_method :incident_payload, :params
+
+ def create_issue
+ label_result = find_or_create_incident_label
+
+ # Create an unlabelled issue if we couldn't create the label
+ # due to a race condition.
+ # See https://gitlab.com/gitlab-org/gitlab-foss/issues/65042
+ extra_params = label_result.success? ? { label_ids: [label_result.payload[:label].id] } : {}
+
+ Issues::CreateService.new(
+ project,
+ current_user,
+ title: issue_title,
+ description: issue_description,
+ **extra_params
+ ).execute
+ end
+
+ def webhook_available?
+ Feature.enabled?(:pagerduty_webhook, project) &&
+ incident_management_setting.pagerduty_active?
+ end
+
+ def forbidden
+ ServiceResponse.error(message: 'Forbidden', http_status: :forbidden)
+ end
+
+ def find_or_create_incident_label
+ ::IncidentManagement::CreateIncidentLabelService.new(project, current_user).execute
+ end
+
+ def issue_title
+ incident_payload['title']
+ end
+
+ def issue_description
+ Gitlab::IncidentManagement::PagerDuty::IncidentIssueDescription.new(incident_payload).to_s
+ end
+
+ def success(issue)
+ ServiceResponse.success(payload: { issue: issue })
+ end
+
+ def error(message, issue = nil)
+ ServiceResponse.error(payload: { issue: issue }, message: message)
+ end
+ end
+ end
+end
diff --git a/app/services/snippets/base_service.rb b/app/services/snippets/base_service.rb
index 1985ced9dd0..d9e8326f159 100644
--- a/app/services/snippets/base_service.rb
+++ b/app/services/snippets/base_service.rb
@@ -6,15 +6,15 @@ module Snippets
CreateRepositoryError = Class.new(StandardError)
- attr_reader :uploaded_assets, :snippet_files
+ attr_reader :uploaded_assets, :snippet_actions
def initialize(project, user = nil, params = {})
super
@uploaded_assets = Array(@params.delete(:files).presence)
- input_actions = Array(@params.delete(:snippet_files).presence)
- @snippet_files = SnippetInputActionCollection.new(input_actions, allowed_actions: restricted_files_actions)
+ input_actions = Array(@params.delete(:snippet_actions).presence)
+ @snippet_actions = SnippetInputActionCollection.new(input_actions, allowed_actions: restricted_files_actions)
filter_spam_check_params
end
@@ -32,18 +32,18 @@ module Snippets
end
def valid_params?
- return true if snippet_files.empty?
+ return true if snippet_actions.empty?
- (params.keys & [:content, :file_name]).none? && snippet_files.valid?
+ (params.keys & [:content, :file_name]).none? && snippet_actions.valid?
end
def invalid_params_error(snippet)
- if snippet_files.valid?
+ if snippet_actions.valid?
[:content, :file_name].each do |key|
snippet.errors.add(key, 'and snippet files cannot be used together') if params.key?(key)
end
else
- snippet.errors.add(:snippet_files, 'have invalid data')
+ snippet.errors.add(:snippet_actions, 'have invalid data')
end
snippet_error_response(snippet, 403)
@@ -75,7 +75,7 @@ module Snippets
end
def files_to_commit(snippet)
- snippet_files.to_commit_actions.presence || build_actions_from_params(snippet)
+ snippet_actions.to_commit_actions.presence || build_actions_from_params(snippet)
end
def build_actions_from_params(snippet)
diff --git a/app/services/snippets/create_service.rb b/app/services/snippets/create_service.rb
index 6039ca2e501..dab47de8a36 100644
--- a/app/services/snippets/create_service.rb
+++ b/app/services/snippets/create_service.rb
@@ -37,13 +37,13 @@ module Snippets
end
end
- # If the snippet_files param is present
+ # If the snippet_actions param is present
# we need to fill content and file_name from
# the model
def create_params
- return params if snippet_files.empty?
+ return params if snippet_actions.empty?
- params.merge(content: snippet_files[0].content, file_name: snippet_files[0].file_path)
+ params.merge(content: snippet_actions[0].content, file_name: snippet_actions[0].file_path)
end
def save_and_commit
diff --git a/app/services/snippets/update_service.rb b/app/services/snippets/update_service.rb
index 1c097ed447a..00146389e22 100644
--- a/app/services/snippets/update_service.rb
+++ b/app/services/snippets/update_service.rb
@@ -37,9 +37,9 @@ module Snippets
# is implemented.
# Once we can perform different operations through this service
# we won't need to keep track of the `content` and `file_name` fields
- if snippet_files.any?
- params[:content] = snippet_files[0].content if snippet_files[0].content
- params[:file_name] = snippet_files[0].file_path
+ if snippet_actions.any?
+ params[:content] = snippet_actions[0].content if snippet_actions[0].content
+ params[:file_name] = snippet_actions[0].file_path
end
snippet.assign_attributes(params)
@@ -109,7 +109,7 @@ module Snippets
end
def committable_attributes?
- (params.stringify_keys.keys & COMMITTABLE_ATTRIBUTES).present? || snippet_files.any?
+ (params.stringify_keys.keys & COMMITTABLE_ATTRIBUTES).present? || snippet_actions.any?
end
def build_actions_from_params(snippet)
diff --git a/app/views/admin/runners/_runner.html.haml b/app/views/admin/runners/_runner.html.haml
index 423472324fe..5c834c2125f 100644
--- a/app/views/admin/runners/_runner.html.haml
+++ b/app/views/admin/runners/_runner.html.haml
@@ -72,8 +72,8 @@
= link_to [:pause, :admin, runner], method: :get, class: 'btn btn-default has-tooltip', title: _('Pause'), ref: 'tooltip', aria: { label: _('Pause') }, data: { placement: 'top', container: 'body', confirm: _('Are you sure?') } do
= icon('pause')
- else
- = link_to [:resume, :admin, runner], method: :get, class: 'btn btn-default has-tooltip', title: _('Resume'), ref: 'tooltip', aria: { label: _('Resume') }, data: { placement: 'top', container: 'body'} do
- = icon('play')
+ = link_to [:resume, :admin, runner], method: :get, class: 'btn btn-default has-tooltip gl-px-3', title: _('Resume'), ref: 'tooltip', aria: { label: _('Resume') }, data: { placement: 'top', container: 'body'} do
+ = sprite_icon('play')
.btn-group
= link_to [:admin, runner], method: :delete, class: 'btn btn-danger has-tooltip', title: _('Remove'), ref: 'tooltip', aria: { label: _('Remove') }, data: { placement: 'top', container: 'body', confirm: _('Are you sure?') } do
= icon('remove')
diff --git a/app/views/ci/group_variables/_index.html.haml b/app/views/ci/group_variables/_index.html.haml
index c350ba5caf7..84bcd42e07c 100644
--- a/app/views/ci/group_variables/_index.html.haml
+++ b/app/views/ci/group_variables/_index.html.haml
@@ -6,8 +6,8 @@
= render 'ci/group_variables/variable_header'
- variables.each do |variable|
.group-variable-row.d-flex.w-100.border-bottom.pt-2.pb-2
- .table-section.section-40.append-right-10.key
+ .table-section.section-40.gl-mr-3.key
= variable.key
- .table-section.section-40.append-right-10
+ .table-section.section-40.gl-mr-3
%a.group-origin-link{ href: group_settings_ci_cd_path(variable.group) }
= variable.group.name
diff --git a/app/views/ci/group_variables/_variable_header.html.haml b/app/views/ci/group_variables/_variable_header.html.haml
index 1a3168cf781..a8d533da0e0 100644
--- a/app/views/ci/group_variables/_variable_header.html.haml
+++ b/app/views/ci/group_variables/_variable_header.html.haml
@@ -1,5 +1,5 @@
.group-variable-keys.d-flex.w-100.align-items-center.pb-2.border-bottom
- .bold.table-section.section-40.append-right-10
+ .bold.table-section.section-40.gl-mr-3
= s_('Key')
- .bold.table-section.section-40.append-right-10
+ .bold.table-section.section-40.gl-mr-3
= s_('Origin')
diff --git a/app/views/ci/variables/_environment_scope_header.html.haml b/app/views/ci/variables/_environment_scope_header.html.haml
index 4ba4ceec16c..fc3b7f925fc 100644
--- a/app/views/ci/variables/_environment_scope_header.html.haml
+++ b/app/views/ci/variables/_environment_scope_header.html.haml
@@ -1,2 +1,2 @@
-.bold.table-section.section-15.append-right-10
+.bold.table-section.section-15.gl-mr-3
= s_('CiVariables|Scope')
diff --git a/app/views/ci/variables/_variable_header.html.haml b/app/views/ci/variables/_variable_header.html.haml
index d3b7a5ae883..65cea00a0c4 100644
--- a/app/views/ci/variables/_variable_header.html.haml
+++ b/app/views/ci/variables/_variable_header.html.haml
@@ -2,11 +2,11 @@
%li.ci-variable-row.m-0.d-none.d-sm-block
.d-flex.w-100.align-items-center.pb-2
- .bold.table-section.section-15.append-right-10
+ .bold.table-section.section-15.gl-mr-3
= s_('CiVariables|Type')
- .bold.table-section.section-15.append-right-10
+ .bold.table-section.section-15.gl-mr-3
= s_('CiVariables|Key')
- .bold.table-section.section-15.append-right-10
+ .bold.table-section.section-15.gl-mr-3
= s_('CiVariables|Value')
- unless only_key_value
.bold.table-section.section-20
diff --git a/app/views/profiles/active_sessions/_active_session.html.haml b/app/views/profiles/active_sessions/_active_session.html.haml
index f3ad0c4c8ad..68f5460e599 100644
--- a/app/views/profiles/active_sessions/_active_session.html.haml
+++ b/app/views/profiles/active_sessions/_active_session.html.haml
@@ -1,7 +1,7 @@
- is_current_session = active_session.current?(session)
%li.list-group-item
- .float-left.append-right-10{ data: { toggle: 'tooltip' }, title: active_session.human_device_type }
+ .float-left.gl-mr-3{ data: { toggle: 'tooltip' }, title: active_session.human_device_type }
= active_session_device_type_icon(active_session)
.description.float-left
diff --git a/app/views/profiles/gpg_keys/_key.html.haml b/app/views/profiles/gpg_keys/_key.html.haml
index 2de5cf2f506..7a10b24c312 100644
--- a/app/views/profiles/gpg_keys/_key.html.haml
+++ b/app/views/profiles/gpg_keys/_key.html.haml
@@ -1,5 +1,5 @@
%li.key-list-item
- .float-left.append-right-10
+ .float-left.gl-mr-3
= icon 'key', class: "settings-list-icon d-none d-sm-block"
.key-list-item-info
- key.emails_with_verified_status.map do |email, verified|
diff --git a/app/views/profiles/keys/_key.html.haml b/app/views/profiles/keys/_key.html.haml
index b227041c9de..c02711e31ae 100644
--- a/app/views/profiles/keys/_key.html.haml
+++ b/app/views/profiles/keys/_key.html.haml
@@ -1,5 +1,5 @@
%li.d-flex.align-items-center.key-list-item
- .append-right-10
+ .gl-mr-3
- if key.valid?
- if key.expired?
%span.d-inline-block.has-tooltip{ title: s_('Profiles|Your key has expired') }
@@ -17,10 +17,10 @@
= key.fingerprint
.key-list-item-dates.d-flex.align-items-start.justify-content-between
- %span.last-used-at.append-right-10
+ %span.last-used-at.gl-mr-3
= s_('Profiles|Last used:')
= key.last_used_at ? time_ago_with_tooltip(key.last_used_at) : _('Never')
- %span.expires.append-right-10
+ %span.expires.gl-mr-3
= s_('Profiles|Expires:')
= key.expires_at ? key.expires_at.to_date : _('Never')
%span.key-created-at
diff --git a/app/views/profiles/passwords/edit.html.haml b/app/views/profiles/passwords/edit.html.haml
index d21db0a6511..fe16c2e2f28 100644
--- a/app/views/profiles/passwords/edit.html.haml
+++ b/app/views/profiles/passwords/edit.html.haml
@@ -30,6 +30,6 @@
= f.label :password_confirmation, _('Password confirmation'), class: 'label-bold'
= f.password_field :password_confirmation, required: true, class: 'form-control', data: { qa_selector: 'confirm_password_field' }
.gl-mt-3.gl-mb-3
- = f.submit _('Save password'), class: "btn btn-success append-right-10", data: { qa_selector: 'save_password_button' }
+ = f.submit _('Save password'), class: "btn btn-success gl-mr-3", data: { qa_selector: 'save_password_button' }
- unless @user.password_automatically_set?
= link_to _('I forgot my password'), reset_profile_password_path, method: :put
diff --git a/app/views/profiles/two_factor_auths/_codes.html.haml b/app/views/profiles/two_factor_auths/_codes.html.haml
index 94fd40ed669..68cd4875a33 100644
--- a/app/views/profiles/two_factor_auths/_codes.html.haml
+++ b/app/views/profiles/two_factor_auths/_codes.html.haml
@@ -9,5 +9,5 @@
%span.monospace= code
.d-flex
- = link_to _('Proceed'), profile_account_path, class: 'btn btn-success append-right-10', data: { qa_selector: 'proceed_button' }
+ = link_to _('Proceed'), profile_account_path, class: 'btn btn-success gl-mr-3', data: { qa_selector: 'proceed_button' }
= link_to _('Download codes'), "data:text/plain;charset=utf-8,#{CGI.escape(@codes.join("\n"))}", download: "gitlab-recovery-codes.txt", class: 'btn btn-default'
diff --git a/app/views/profiles/two_factor_auths/show.html.haml b/app/views/profiles/two_factor_auths/show.html.haml
index b8c5d626d17..0fde3e5fb10 100644
--- a/app/views/profiles/two_factor_auths/show.html.haml
+++ b/app/views/profiles/two_factor_auths/show.html.haml
@@ -19,7 +19,7 @@
= link_to _('Disable two-factor authentication'), profile_two_factor_auth_path,
method: :delete,
data: { confirm: _('Are you sure? This will invalidate your registered applications and U2F devices.') },
- class: 'btn btn-danger append-right-10'
+ class: 'btn btn-danger gl-mr-3'
= form_tag codes_profile_two_factor_auth_path, {style: 'display: inline-block', method: :post} do |f|
= submit_tag _('Regenerate recovery codes'), class: 'btn'
diff --git a/app/views/projects/blob/_editor.html.haml b/app/views/projects/blob/_editor.html.haml
index 1e9cf68f3a5..b06ae31e73f 100644
--- a/app/views/projects/blob/_editor.html.haml
+++ b/app/views/projects/blob/_editor.html.haml
@@ -8,13 +8,13 @@
= sprite_icon('fork', size: 12)
= ref
- if current_action?(:edit) || current_action?(:update)
- %span.pull-left.append-right-10
+ %span.pull-left.gl-mr-3
= text_field_tag 'file_path', (params[:file_path] || @path),
class: 'form-control new-file-path js-file-path-name-input'
= render 'template_selectors'
- if current_action?(:new) || current_action?(:create)
- %span.pull-left.append-right-10
+ %span.pull-left.gl-mr-3
\/
= text_field_tag 'file_name', params[:file_name], placeholder: "File name",
required: true, class: 'form-control new-file-name js-file-path-name-input', value: params[:file_name] || (should_suggest_gitlab_ci_yml? ? '.gitlab-ci.yml' : '')
diff --git a/app/views/projects/commit/_commit_box.html.haml b/app/views/projects/commit/_commit_box.html.haml
index 4442bdcdf1d..71cf6ca6922 100644
--- a/app/views/projects/commit/_commit_box.html.haml
+++ b/app/views/projects/commit/_commit_box.html.haml
@@ -22,10 +22,10 @@
.header-action-buttons
- if defined?(@notes_count) && @notes_count > 0
- %span.btn.disabled.btn-grouped.d-none.d-sm-block.append-right-10.has-tooltip{ title: n_("%d comment on this commit", "%d comments on this commit", @notes_count) % @notes_count }
+ %span.btn.disabled.btn-grouped.d-none.d-sm-block.gl-mr-3.has-tooltip{ title: n_("%d comment on this commit", "%d comments on this commit", @notes_count) % @notes_count }
= sprite_icon('comment')
= @notes_count
- = link_to project_tree_path(@project, @commit), class: "btn btn-default append-right-10 d-none d-sm-none d-md-inline" do
+ = link_to project_tree_path(@project, @commit), class: "btn btn-default gl-mr-3 d-none d-sm-none d-md-inline" do
#{ _('Browse files') }
.dropdown.inline
%a.btn.btn-default.dropdown-toggle.qa-options-button.d-md-inline{ data: { toggle: "dropdown" } }
diff --git a/app/views/projects/issues/_nav_btns.html.haml b/app/views/projects/issues/_nav_btns.html.haml
index 71c9bb36936..cc6ca4aca4a 100644
--- a/app/views/projects/issues/_nav_btns.html.haml
+++ b/app/views/projects/issues/_nav_btns.html.haml
@@ -14,7 +14,7 @@
= render 'projects/issues/import_csv/button'
- if @can_bulk_update
- = button_tag _("Edit issues"), class: "btn btn-default append-right-10 js-bulk-update-toggle"
+ = button_tag _("Edit issues"), class: "btn btn-default gl-mr-3 js-bulk-update-toggle"
- if show_new_issue_link?(@project)
= link_to _("New issue"), new_project_issue_path(@project,
issue: { assignee_id: finder.assignee.try(:id),
diff --git a/app/views/projects/merge_requests/_discussion.html.haml b/app/views/projects/merge_requests/_discussion.html.haml
index 3303aa72604..ecb51aca847 100644
--- a/app/views/projects/merge_requests/_discussion.html.haml
+++ b/app/views/projects/merge_requests/_discussion.html.haml
@@ -5,7 +5,7 @@
- if @merge_request.reopenable?
= link_to 'Reopen merge request', merge_request_path(@merge_request, merge_request: { state_event: :reopen }), method: :put, class: "btn btn-nr btn-comment btn-reopen reopen-mr-link js-note-target-close js-note-target-reopen", title: "Reopen merge request", data: { original_text: "Reopen merge request", alternative_text: "Comment & reopen merge request"}
%comment-and-resolve-btn{ "inline-template" => true }
- %button.btn.btn-nr.btn-default.append-right-10.js-comment-resolve-button{ "v-if" => "showButton", type: "submit", data: { project_path: "#{project_path(@merge_request.project)}" } }
+ %button.btn.btn-nr.btn-default.gl-mr-3.js-comment-resolve-button{ "v-if" => "showButton", type: "submit", data: { project_path: "#{project_path(@merge_request.project)}" } }
{{ buttonText }}
#notes= render "shared/notes/notes_with_form", :autocomplete => true
diff --git a/app/views/projects/merge_requests/_nav_btns.html.haml b/app/views/projects/merge_requests/_nav_btns.html.haml
index b7498216334..2ef10365c18 100644
--- a/app/views/projects/merge_requests/_nav_btns.html.haml
+++ b/app/views/projects/merge_requests/_nav_btns.html.haml
@@ -1,5 +1,5 @@
- if @can_bulk_update
- = button_tag "Edit merge requests", class: "btn append-right-10 js-bulk-update-toggle"
+ = button_tag "Edit merge requests", class: "btn gl-mr-3 js-bulk-update-toggle"
- if merge_project
= link_to new_merge_request_path, class: "btn btn-success", title: "New merge request" do
New merge request
diff --git a/app/views/projects/mirrors/_ssh_host_keys.html.haml b/app/views/projects/mirrors/_ssh_host_keys.html.haml
index ca8ed417255..236ede32d31 100644
--- a/app/views/projects/mirrors/_ssh_host_keys.html.haml
+++ b/app/views/projects/mirrors/_ssh_host_keys.html.haml
@@ -3,7 +3,7 @@
- verified_at = mirror.ssh_known_hosts_verified_at
.form-group.js-ssh-host-keys-section{ class: ('collapse' unless mirror.ssh_mirror_url?) }
- %button.btn.btn-inverted.btn-secondary.inline.js-detect-host-keys.append-right-10{ type: 'button', data: { qa_selector: 'detect_host_keys' } }
+ %button.btn.btn-inverted.btn-secondary.inline.js-detect-host-keys.gl-mr-3{ type: 'button', data: { qa_selector: 'detect_host_keys' } }
.js-spinner.d-none.spinner.mr-1
= _('Detect host keys')
.fingerprint-ssh-info.js-fingerprint-ssh-info.prepend-top-10.append-bottom-10{ class: ('collapse' unless mirror.ssh_mirror_url?) }
diff --git a/app/views/projects/no_repo.html.haml b/app/views/projects/no_repo.html.haml
index 7748aadf44d..3a9e9108256 100644
--- a/app/views/projects/no_repo.html.haml
+++ b/app/views/projects/no_repo.html.haml
@@ -15,7 +15,7 @@
= link_to project_repository_path(@project), method: :post, class: 'btn btn-primary' do
#{ _('Create empty repository') }
- %strong.prepend-left-10.append-right-10 or
+ %strong.prepend-left-10.gl-mr-3 or
= link_to new_project_import_path(@project), class: 'btn' do
#{ _('Import repository') }
diff --git a/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml b/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml
index 8d88f0be083..f48763cb544 100644
--- a/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml
+++ b/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml
@@ -27,8 +27,8 @@
%td
.float-right.btn-group
- if can?(current_user, :play_pipeline_schedule, pipeline_schedule)
- = link_to play_pipeline_schedule_path(pipeline_schedule), method: :post, title: s_('Play'), class: 'btn' do
- = icon('play')
+ = link_to play_pipeline_schedule_path(pipeline_schedule), method: :post, title: s_('Play'), class: 'btn btn-svg gl-display-flex gl-align-items-center gl-justify-content-center' do
+ = sprite_icon('play')
- if can?(current_user, :take_ownership_pipeline_schedule, pipeline_schedule)
= link_to take_ownership_pipeline_schedule_path(pipeline_schedule), method: :post, title: s_('PipelineSchedules|Take ownership'), class: 'btn' do
= s_('PipelineSchedules|Take ownership')
diff --git a/app/views/projects/project_templates/_built_in_templates.html.haml b/app/views/projects/project_templates/_built_in_templates.html.haml
index eb41a3e0785..43352952b37 100644
--- a/app/views/projects/project_templates/_built_in_templates.html.haml
+++ b/app/views/projects/project_templates/_built_in_templates.html.haml
@@ -1,6 +1,6 @@
- Gitlab::ProjectTemplate.all.each do |template|
.template-option.d-flex.align-items-center{ data: { qa_selector: 'template_option_row' } }
- .logo.append-right-10.px-1
+ .logo.gl-mr-3.px-1
= image_tag template.logo, size: 32, class: "btn-template-icon icon-#{template.name}"
.description
%strong
@@ -9,7 +9,7 @@
.text-muted
= template.description
.controls.d-flex.align-items-center
- %a.btn.btn-default.append-right-10{ href: template.preview, rel: 'noopener noreferrer', target: '_blank', data: { track_label: "template_preview", track_property: template.name, track_event: "click_button", track_value: "" } }
+ %a.btn.btn-default.gl-mr-3{ href: template.preview, rel: 'noopener noreferrer', target: '_blank', data: { track_label: "template_preview", track_property: template.name, track_event: "click_button", track_value: "" } }
= _("Preview")
%label.btn.btn-success.template-button.choose-template.gl-mb-0{ for: template.name }
%input{ type: "radio", autocomplete: "off", name: "project[template_name]", id: template.name, value: template.name, data: { track_label: "template_use", track_property: template.name, track_event: "click_button", track_value: "" } }
diff --git a/app/views/projects/project_templates/_project_fields_form.html.haml b/app/views/projects/project_templates/_project_fields_form.html.haml
index c96010550d8..201e2d5b5fb 100644
--- a/app/views/projects/project_templates/_project_fields_form.html.haml
+++ b/app/views/projects/project_templates/_project_fields_form.html.haml
@@ -5,7 +5,7 @@
.input-group.template-input-group
.input-group-prepend
.input-group-text
- .selected-icon.append-right-10
+ .selected-icon.gl-mr-3
.selected-template
.input-group-append
%button.btn.btn-default.change-template{ type: "button" }
diff --git a/app/views/sent_notifications/unsubscribe.html.haml b/app/views/sent_notifications/unsubscribe.html.haml
index 1eecbe3bc0e..7aeecf26c39 100644
--- a/app/views/sent_notifications/unsubscribe.html.haml
+++ b/app/views/sent_notifications/unsubscribe.html.haml
@@ -15,5 +15,5 @@
%p
= link_to _('Unsubscribe'), unsubscribe_sent_notification_path(@sent_notification, force: true),
- class: 'btn btn-primary append-right-10'
- = link_to _('Cancel'), new_user_session_path, class: 'btn append-right-10'
+ class: 'btn btn-primary gl-mr-3'
+ = link_to _('Cancel'), new_user_session_path, class: 'btn gl-mr-3'
diff --git a/app/views/shared/groups/_dropdown.html.haml b/app/views/shared/groups/_dropdown.html.haml
index f4915440cb2..9d2d3ce20c7 100644
--- a/app/views/shared/groups/_dropdown.html.haml
+++ b/app/views/shared/groups/_dropdown.html.haml
@@ -8,7 +8,7 @@
- else
- default_sort_by = sort_value_recently_created
-.dropdown.inline.js-group-filter-dropdown-wrap.append-right-10
+.dropdown.inline.js-group-filter-dropdown-wrap.gl-mr-3
%button.dropdown-menu-toggle{ type: 'button', 'data-toggle' => 'dropdown' }
%span.dropdown-label
= options_hash[default_sort_by]
diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml
index cc5bd4d67c9..f54457b8b33 100644
--- a/app/views/shared/issuable/_form.html.haml
+++ b/app/views/shared/issuable/_form.html.haml
@@ -69,7 +69,7 @@
= link_to 'Delete', polymorphic_path([@project.namespace.becomes(Namespace), @project, issuable], params: { destroy_confirm: true }), data: { confirm: "#{issuable.human_class_name} will be removed! Are you sure?" }, method: :delete, class: 'btn btn-danger btn-grouped'
= link_to 'Cancel', polymorphic_path([@project.namespace.becomes(Namespace), @project, issuable]), class: 'btn btn-grouped btn-cancel'
- %span.append-right-10
+ %span.gl-mr-3
- if issuable.new_record?
= form.submit "Submit #{issuable.class.model_name.human.downcase}", class: 'btn btn-success qa-issuable-create-button'
- else
diff --git a/app/views/shared/milestones/_deprecation_message.html.haml b/app/views/shared/milestones/_deprecation_message.html.haml
index ba5eb54f017..31b8b383fe1 100644
--- a/app/views/shared/milestones/_deprecation_message.html.haml
+++ b/app/views/shared/milestones/_deprecation_message.html.haml
@@ -1,6 +1,6 @@
.banner-callout.compact.milestone-deprecation-message.js-milestone-deprecation-message.prepend-top-20
.banner-graphic= image_tag 'illustrations/milestone_removing-page.svg'
- .banner-body.prepend-left-10.append-right-10
+ .banner-body.prepend-left-10.gl-mr-3
%h5.banner-title.gl-mt-0= _('This page will be removed in a future release.')
%p.milestone-banner-text= _('Use group milestones to manage issues from multiple projects in the same milestone.')
= button_tag _('Promote these project milestones into a group milestone.'), class: 'btn btn-link js-popover-link text-align-left milestone-banner-link'
diff --git a/app/views/shared/notes/_comment_button.html.haml b/app/views/shared/notes/_comment_button.html.haml
index 748bb1e6534..e151e55d0d2 100644
--- a/app/views/shared/notes/_comment_button.html.haml
+++ b/app/views/shared/notes/_comment_button.html.haml
@@ -1,6 +1,6 @@
- noteable_name = @note.noteable.human_class_name
-.float-left.btn-group.append-right-10.droplab-dropdown.comment-type-dropdown.js-comment-type-dropdown
+.float-left.btn-group.gl-mr-3.droplab-dropdown.comment-type-dropdown.js-comment-type-dropdown
%input.btn.btn-nr.btn-success.js-comment-button.js-comment-submit-button{ type: 'submit', value: _('Comment'), data: { qa_selector: 'comment_button' } }
- if @note.can_be_discussion_note?
diff --git a/app/views/shared/projects/_project.html.haml b/app/views/shared/projects/_project.html.haml
index ddf0bdeca4e..626e94e0202 100644
--- a/app/views/shared/projects/_project.html.haml
+++ b/app/views/shared/projects/_project.html.haml
@@ -39,11 +39,11 @@
%span.project-name<
= project.name
- %span.metadata-info.visibility-icon.append-right-10.gl-mt-3.text-secondary.has-tooltip{ data: { container: 'body', placement: 'top' }, title: visibility_icon_description(project) }
+ %span.metadata-info.visibility-icon.gl-mr-3.gl-mt-3.text-secondary.has-tooltip{ data: { container: 'body', placement: 'top' }, title: visibility_icon_description(project) }
= visibility_level_icon(project.visibility_level, fw: true)
- if explore_projects_tab? && project_license_name(project)
- %span.metadata-info.d-inline-flex.align-items-center.append-right-10.gl-mt-3
+ %span.metadata-info.d-inline-flex.align-items-center.gl-mr-3.gl-mt-3
= sprite_icon('scale', size: 14, css_class: 'gl-mr-2')
= project_license_name(project)
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index 0224b0db3dc..b079a114c71 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -691,6 +691,14 @@
:weight: 2
:idempotent: true
:tags: []
+- :name: incident_management:incident_management_pager_duty_process_incident
+ :feature_category: :incident_management
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 2
+ :idempotent:
+ :tags: []
- :name: incident_management:incident_management_process_alert
:feature_category: :incident_management
:has_external_dependencies:
@@ -869,7 +877,7 @@
:tags: []
- :name: pipeline_background:ci_pipeline_success_unlock_artifacts
:feature_category: :continuous_integration
- :has_external_dependencies:
+ :has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
:weight: 1
@@ -877,7 +885,7 @@
:tags: []
- :name: pipeline_background:ci_ref_delete_unlock_artifacts
:feature_category: :continuous_integration
- :has_external_dependencies:
+ :has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
:weight: 1
@@ -1670,11 +1678,11 @@
:tags: []
- :name: service_desk_email_receiver
:feature_category: :issue_tracking
- :has_external_dependencies:
+ :has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
:weight: 1
- :idempotent:
+ :idempotent:
:tags: []
- :name: system_hook_push
:feature_category: :source_code_management
diff --git a/app/workers/incident_management/pager_duty/process_incident_worker.rb b/app/workers/incident_management/pager_duty/process_incident_worker.rb
new file mode 100644
index 00000000000..3f378b012a1
--- /dev/null
+++ b/app/workers/incident_management/pager_duty/process_incident_worker.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+module IncidentManagement
+ module PagerDuty
+ class ProcessIncidentWorker # rubocop:disable Scalability/IdempotentWorker
+ include ApplicationWorker
+
+ queue_namespace :incident_management
+ feature_category :incident_management
+
+ def perform(project_id, incident_payload)
+ return unless project_id
+
+ project = find_project(project_id)
+ return unless project
+
+ result = create_issue(project, incident_payload)
+
+ log_error(result) if result.error?
+ end
+
+ private
+
+ def find_project(project_id)
+ Project.find_by_id(project_id)
+ end
+
+ def create_issue(project, incident_payload)
+ ::IncidentManagement::PagerDuty::CreateIncidentIssueService
+ .new(project, incident_payload)
+ .execute
+ end
+
+ def log_error(result)
+ Gitlab::AppLogger.warn(
+ message: 'Cannot create issue for PagerDuty incident',
+ issue_errors: result.message
+ )
+ end
+ end
+ end
+end