summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2019-10-18 00:07:45 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2019-10-18 00:07:45 +0000
commit7c077d960393e14b56d43cceaa7f609c703ac55f (patch)
treec3a5d79554b9be1d7434c8e9a8fcae35ab64af32
parentda35510cdad8f8d3cb6c119682dc2735531983cd (diff)
downloadgitlab-ce-7c077d960393e14b56d43cceaa7f609c703ac55f.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/create_cluster/eks_cluster/components/create_eks_cluster.vue13
-rw-r--r--app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue22
-rw-r--r--app/assets/javascripts/create_cluster/eks_cluster/index.js19
-rw-r--r--app/assets/javascripts/error_tracking/components/error_tracking_list.vue22
-rw-r--r--app/assets/javascripts/error_tracking/utils.js23
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard.vue23
-rw-r--r--app/assets/javascripts/monitoring/components/panel_type.vue14
-rw-r--r--app/assets/javascripts/monitoring/utils.js43
-rw-r--r--app/assets/javascripts/pages/projects/clusters/new/index.js8
-rw-r--r--app/assets/javascripts/vue_shared/directives/track_event.js20
-rw-r--r--app/controllers/projects/settings/operations_controller.rb5
-rw-r--r--app/services/issues/zoom_link_service.rb10
-rw-r--r--app/views/clusters/clusters/cloud_providers/_cloud_provider_button.html.haml2
-rw-r--r--app/views/clusters/clusters/cloud_providers/_cloud_provider_selector.html.haml4
-rw-r--r--app/views/clusters/clusters/eks/_index.html.haml3
-rw-r--r--app/views/clusters/clusters/gcp/_form.html.haml5
-rw-r--r--app/views/clusters/clusters/gcp/_gcp_not_configured.html.haml3
-rw-r--r--app/views/clusters/clusters/gcp/_signin_with_google_button.html.haml4
-rw-r--r--app/views/clusters/clusters/new.html.haml32
-rw-r--r--changelogs/unreleased/31923-Snowplow-custom-events-Monitor.yml5
-rw-r--r--doc/administration/gitaly/index.md2
-rw-r--r--doc/administration/index.md2
-rw-r--r--doc/administration/job_artifacts.md2
-rw-r--r--doc/administration/job_logs.md169
-rw-r--r--doc/administration/job_traces.md168
-rw-r--r--doc/api/jobs.md14
-rw-r--r--doc/ci/pipelines.md4
-rw-r--r--doc/ci/runners/README.md12
-rw-r--r--doc/ci/ssh_keys/README.md4
-rw-r--r--doc/ci/variables/README.md16
-rw-r--r--doc/ci/variables/predefined_variables.md2
-rw-r--r--doc/ci/yaml/README.md2
-rw-r--r--doc/install/installation.md2
-rw-r--r--doc/user/group/saml_sso/index.md19
-rw-r--r--lib/gitlab/gitaly_client/conflict_files_stitcher.rb7
-rw-r--r--lib/gitlab/gitaly_client/conflicts_service.rb2
-rw-r--r--lib/gitlab/tracking/incident_management.rb41
-rw-r--r--locale/gitlab.pot17
-rw-r--r--spec/features/projects/clusters/eks_spec.rb34
-rw-r--r--spec/features/projects/clusters/gcp_spec.rb2
-rw-r--r--spec/features/projects/clusters_spec.rb2
-rw-r--r--spec/frontend/create_cluster/eks_cluster/components/eks_cluster_configuration_form_spec.js1
-rw-r--r--spec/frontend/error_tracking/utils_spec.js27
-rw-r--r--spec/frontend/monitoring/utils_spec.js54
-rw-r--r--spec/frontend/vue_shared/directives/track_event_spec.js49
-rw-r--r--spec/lib/gitlab/gitaly_client/conflict_files_stitcher_spec.rb2
-rw-r--r--spec/lib/gitlab/tracking/incident_management_spec.rb78
-rw-r--r--spec/services/issues/zoom_link_service_spec.rb13
48 files changed, 784 insertions, 243 deletions
diff --git a/app/assets/javascripts/create_cluster/eks_cluster/components/create_eks_cluster.vue b/app/assets/javascripts/create_cluster/eks_cluster/components/create_eks_cluster.vue
index b865c9deb72..22ee368b8e0 100644
--- a/app/assets/javascripts/create_cluster/eks_cluster/components/create_eks_cluster.vue
+++ b/app/assets/javascripts/create_cluster/eks_cluster/components/create_eks_cluster.vue
@@ -12,11 +12,18 @@ export default {
type: String,
required: true,
},
+ kubernetesIntegrationHelpPath: {
+ type: String,
+ required: true,
+ },
},
};
</script>
<template>
- <eks-cluster-configuration-form
- :gitlab-managed-cluster-help-path="gitlabManagedClusterHelpPath"
- />
+ <div class="js-create-eks-cluster">
+ <eks-cluster-configuration-form
+ :gitlab-managed-cluster-help-path="gitlabManagedClusterHelpPath"
+ :kubernetes-integration-help-path="kubernetesIntegrationHelpPath"
+ />
+ </div>
</template>
diff --git a/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue b/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue
index d451516dd35..1188cf08850 100644
--- a/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue
+++ b/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue
@@ -35,6 +35,10 @@ export default {
type: String,
required: true,
},
+ kubernetesIntegrationHelpPath: {
+ type: String,
+ required: true,
+ },
},
computed: {
...mapState([
@@ -94,6 +98,20 @@ export default {
securityGroupDropdownDisabled() {
return !this.selectedVpc;
},
+ kubernetesIntegrationHelpText() {
+ const escapedUrl = _.escape(this.kubernetesIntegrationHelpPath);
+
+ return sprintf(
+ s__(
+ 'ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration.',
+ ),
+ {
+ link_start: `<a href="${escapedUrl}" target="_blank" rel="noopener noreferrer">`,
+ link_end: '</a>',
+ },
+ false,
+ );
+ },
roleDropdownHelpText() {
return sprintf(
s__(
@@ -212,6 +230,10 @@ export default {
</script>
<template>
<form name="eks-cluster-configuration-form">
+ <h2>
+ {{ s__('ClusterIntegration|Enter the details for your Amazon EKS Kubernetes cluster') }}
+ </h2>
+ <p v-html="kubernetesIntegrationHelpText"></p>
<div class="form-group">
<label class="label-bold" for="eks-cluster-name">{{
s__('ClusterIntegration|Kubernetes cluster name')
diff --git a/app/assets/javascripts/create_cluster/eks_cluster/index.js b/app/assets/javascripts/create_cluster/eks_cluster/index.js
index 77454a2bc00..1f595e9b2df 100644
--- a/app/assets/javascripts/create_cluster/eks_cluster/index.js
+++ b/app/assets/javascripts/create_cluster/eks_cluster/index.js
@@ -5,25 +5,22 @@ import createStore from './store';
Vue.use(Vuex);
-export default () =>
- new Vue({
- el: '.js-create-eks-cluster-form-container',
+export default el => {
+ const { gitlabManagedClusterHelpPath, kubernetesIntegrationHelpPath } = el.dataset;
+
+ return new Vue({
+ el,
store: createStore(),
components: {
CreateEksCluster,
},
- data() {
- const { gitlabManagedClusterHelpPath } = document.querySelector(this.$options.el).dataset;
-
- return {
- gitlabManagedClusterHelpPath,
- };
- },
render(createElement) {
return createElement('create-eks-cluster', {
props: {
- gitlabManagedClusterHelpPath: this.gitlabManagedClusterHelpPath,
+ gitlabManagedClusterHelpPath,
+ kubernetesIntegrationHelpPath,
},
});
},
});
+};
diff --git a/app/assets/javascripts/error_tracking/components/error_tracking_list.vue b/app/assets/javascripts/error_tracking/components/error_tracking_list.vue
index 3528f0a9335..cd298e2c692 100644
--- a/app/assets/javascripts/error_tracking/components/error_tracking_list.vue
+++ b/app/assets/javascripts/error_tracking/components/error_tracking_list.vue
@@ -4,6 +4,8 @@ import { GlEmptyState, GlButton, GlLink, GlLoadingIcon, GlTable } from '@gitlab/
import Icon from '~/vue_shared/components/icon.vue';
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
import { __ } from '~/locale';
+import TrackEventDirective from '~/vue_shared/directives/track_event';
+import { trackViewInSentryOptions, trackClickErrorLinkToSentryOptions } from '../utils';
export default {
fields: [
@@ -21,6 +23,9 @@ export default {
Icon,
TimeAgo,
},
+ directives: {
+ TrackEvent: TrackEventDirective,
+ },
props: {
indexPath: {
type: String,
@@ -53,6 +58,8 @@ export default {
},
methods: {
...mapActions(['startPolling', 'restartPolling']),
+ trackViewInSentryOptions,
+ trackClickErrorLinkToSentryOptions,
},
};
</script>
@@ -65,7 +72,13 @@ export default {
</div>
<div v-else>
<div class="d-flex justify-content-end">
- <gl-button class="my-3 ml-auto" variant="primary" :href="externalUrl" target="_blank">
+ <gl-button
+ v-track-event="trackViewInSentryOptions(externalUrl)"
+ class="my-3 ml-auto"
+ variant="primary"
+ :href="externalUrl"
+ target="_blank"
+ >
{{ __('View in Sentry') }}
<icon name="external-link" class="flex-shrink-0" />
</gl-button>
@@ -80,7 +93,12 @@ export default {
</template>
<template slot="error" slot-scope="errors">
<div class="d-flex flex-column">
- <gl-link :href="errors.item.externalUrl" class="d-flex text-dark" target="_blank">
+ <gl-link
+ v-track-event="trackClickErrorLinkToSentryOptions(errors.item.externalUrl)"
+ :href="errors.item.externalUrl"
+ class="d-flex text-dark"
+ target="_blank"
+ >
<strong class="text-truncate">{{ errors.item.title.trim() }}</strong>
<icon name="external-link" class="ml-1 flex-shrink-0" />
</gl-link>
diff --git a/app/assets/javascripts/error_tracking/utils.js b/app/assets/javascripts/error_tracking/utils.js
new file mode 100644
index 00000000000..b832b1371b1
--- /dev/null
+++ b/app/assets/javascripts/error_tracking/utils.js
@@ -0,0 +1,23 @@
+/* eslint-disable @gitlab/i18n/no-non-i18n-strings */
+
+/**
+ * Tracks snowplow event when user clicks View in Sentry btn
+ * @param {String} externalUrl that will be send as a property for the event
+ */
+export const trackViewInSentryOptions = url => ({
+ category: 'Error Tracking',
+ action: 'click_view_in_sentry',
+ label: 'External Url',
+ property: url,
+});
+
+/**
+ * Tracks snowplow event when User clicks on error link to Sentry
+ * @param {String} externalUrl that will be send as a property for the event
+ */
+export const trackClickErrorLinkToSentryOptions = url => ({
+ category: 'Error Tracking',
+ action: 'click_error_link_to_sentry',
+ label: 'Error Link',
+ property: url,
+});
diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue
index 09afa16e283..2e35ef8d4b0 100644
--- a/app/assets/javascripts/monitoring/components/dashboard.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard.vue
@@ -21,7 +21,14 @@ import MonitorSingleStatChart from './charts/single_stat.vue';
import GraphGroup from './graph_group.vue';
import EmptyState from './empty_state.vue';
import { sidebarAnimationDuration, timeWindows } from '../constants';
-import { getTimeDiff, getTimeWindow } from '../utils';
+import TrackEventDirective from '~/vue_shared/directives/track_event';
+
+import {
+ getTimeDiff,
+ getTimeWindow,
+ downloadCSVOptions,
+ generateLinkToChartOptions,
+} from '../utils';
let sidebarMutationObserver;
@@ -43,6 +50,7 @@ export default {
directives: {
GlModal: GlModalDirective,
GlTooltip: GlTooltipDirective,
+ TrackEvent: TrackEventDirective,
},
props: {
externalDashboardUrl: {
@@ -322,6 +330,8 @@ export default {
groupHasData(group) {
return this.chartsWithData(group.metrics).length > 0;
},
+ downloadCSVOptions,
+ generateLinkToChartOptions,
},
addMetric: {
title: s__('Metrics|Add metric'),
@@ -552,10 +562,19 @@ export default {
<template slot="button-content">
<icon name="ellipsis_v" class="text-secondary" />
</template>
- <gl-dropdown-item :href="downloadCsv(graphData)" download="chart_metrics.csv">
+ <gl-dropdown-item
+ v-track-event="downloadCSVOptions(graphData.title)"
+ :href="downloadCsv(graphData)"
+ download="chart_metrics.csv"
+ >
{{ __('Download CSV') }}
</gl-dropdown-item>
<gl-dropdown-item
+ v-track-event="
+ generateLinkToChartOptions(
+ generateLink(groupData.group, graphData.title, graphData.y_label),
+ )
+ "
class="js-chart-link"
:data-clipboard-text="
generateLink(groupData.group, graphData.title, graphData.y_label)
diff --git a/app/assets/javascripts/monitoring/components/panel_type.vue b/app/assets/javascripts/monitoring/components/panel_type.vue
index af0d8335c43..1a14d06f4c8 100644
--- a/app/assets/javascripts/monitoring/components/panel_type.vue
+++ b/app/assets/javascripts/monitoring/components/panel_type.vue
@@ -13,6 +13,8 @@ import Icon from '~/vue_shared/components/icon.vue';
import MonitorTimeSeriesChart from './charts/time_series.vue';
import MonitorSingleStatChart from './charts/single_stat.vue';
import MonitorEmptyChart from './charts/empty_chart.vue';
+import TrackEventDirective from '~/vue_shared/directives/track_event';
+import { downloadCSVOptions, generateLinkToChartOptions } from '../utils';
export default {
components: {
@@ -27,6 +29,7 @@ export default {
directives: {
GlModal: GlModalDirective,
GlTooltip: GlTooltipDirective,
+ TrackEvent: TrackEventDirective,
},
props: {
clipboardText: {
@@ -84,6 +87,8 @@ export default {
showToast() {
this.$toast.show(__('Link copied'));
},
+ downloadCSVOptions,
+ generateLinkToChartOptions,
},
};
</script>
@@ -121,13 +126,18 @@ export default {
<template slot="button-content">
<icon name="ellipsis_v" class="text-secondary" />
</template>
- <gl-dropdown-item :href="downloadCsv" download="chart_metrics.csv">
+ <gl-dropdown-item
+ v-track-event="downloadCSVOptions(graphData.title)"
+ :href="downloadCsv"
+ download="chart_metrics.csv"
+ >
{{ __('Download CSV') }}
</gl-dropdown-item>
<gl-dropdown-item
+ v-track-event="generateLinkToChartOptions(clipboardText)"
class="js-chart-link"
:data-clipboard-text="clipboardText"
- @click="showToast"
+ @click="showToast(clipboardText)"
>
{{ __('Generate link to chart') }}
</gl-dropdown-item>
diff --git a/app/assets/javascripts/monitoring/utils.js b/app/assets/javascripts/monitoring/utils.js
index a134b4e3c33..9049695b992 100644
--- a/app/assets/javascripts/monitoring/utils.js
+++ b/app/assets/javascripts/monitoring/utils.js
@@ -45,4 +45,47 @@ export const graphDataValidatorForValues = (isValues, graphData) => {
);
};
+/* eslint-disable @gitlab/i18n/no-non-i18n-strings */
+/**
+ * Checks that element that triggered event is located on cluster health check dashboard
+ * @param {HTMLElement} element to check against
+ * @returns {boolean}
+ */
+const isClusterHealthBoard = () => (document.body.dataset.page || '').includes(':clusters:show');
+
+/**
+ * Tracks snowplow event when user generates link to metric chart
+ * @param {String} chart link that will be sent as a property for the event
+ * @return {Object} config object for event tracking
+ */
+export const generateLinkToChartOptions = chartLink => {
+ const isCLusterHealthBoard = isClusterHealthBoard();
+
+ const category = isCLusterHealthBoard
+ ? 'Cluster Monitoring'
+ : 'Incident Management::Embedded metrics';
+ const action = isCLusterHealthBoard
+ ? 'generate_link_to_cluster_metric_chart'
+ : 'generate_link_to_metrics_chart';
+
+ return { category, action, label: 'Chart link', property: chartLink };
+};
+
+/**
+ * Tracks snowplow event when user downloads CSV of cluster metric
+ * @param {String} chart title that will be sent as a property for the event
+ */
+export const downloadCSVOptions = title => {
+ const isCLusterHealthBoard = isClusterHealthBoard();
+
+ const category = isCLusterHealthBoard
+ ? 'Cluster Monitoring'
+ : 'Incident Management::Embedded metrics';
+ const action = isCLusterHealthBoard
+ ? 'download_csv_of_cluster_metric_chart'
+ : 'download_csv_of_metrics_dashboard_chart';
+
+ return { category, action, label: 'Chart title', property: title };
+};
+
export default {};
diff --git a/app/assets/javascripts/pages/projects/clusters/new/index.js b/app/assets/javascripts/pages/projects/clusters/new/index.js
index 55aa29c9797..14d5ab21555 100644
--- a/app/assets/javascripts/pages/projects/clusters/new/index.js
+++ b/app/assets/javascripts/pages/projects/clusters/new/index.js
@@ -1,7 +1,13 @@
document.addEventListener('DOMContentLoaded', () => {
if (gon.features.createEksClusters) {
import(/* webpackChunkName: 'eks_cluster' */ '~/create_cluster/eks_cluster')
- .then(({ default: initCreateEKSCluster }) => initCreateEKSCluster())
+ .then(({ default: initCreateEKSCluster }) => {
+ const el = document.querySelector('.js-create-eks-cluster-form-container');
+
+ if (el) {
+ initCreateEKSCluster(el);
+ }
+ })
.catch(() => {});
}
});
diff --git a/app/assets/javascripts/vue_shared/directives/track_event.js b/app/assets/javascripts/vue_shared/directives/track_event.js
new file mode 100644
index 00000000000..d1c05c5c267
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/directives/track_event.js
@@ -0,0 +1,20 @@
+import Tracking from '~/tracking';
+
+export default {
+ bind(el, binding) {
+ el.dataset.trackingOptions = JSON.stringify(binding.value || {});
+
+ el.addEventListener('click', () => {
+ const { category, action, label, property, value } = JSON.parse(el.dataset.trackingOptions);
+ if (!category || !action) {
+ return;
+ }
+ Tracking.event(category, action, { label, property, value });
+ });
+ },
+ update(el, binding) {
+ if (binding.value !== binding.oldValue) {
+ el.dataset.trackingOptions = JSON.stringify(binding.value || {});
+ }
+ },
+};
diff --git a/app/controllers/projects/settings/operations_controller.rb b/app/controllers/projects/settings/operations_controller.rb
index 6110a7759ad..5bf3618b389 100644
--- a/app/controllers/projects/settings/operations_controller.rb
+++ b/app/controllers/projects/settings/operations_controller.rb
@@ -13,9 +13,14 @@ module Projects
def update
result = ::Projects::Operations::UpdateService.new(project, current_user, update_params).execute
+ track_events(result)
render_update_response(result)
end
+ # overridden in EE
+ def track_events(result)
+ end
+
private
# overridden in EE
diff --git a/app/services/issues/zoom_link_service.rb b/app/services/issues/zoom_link_service.rb
index 6cc1cdeeff9..561c86475e5 100644
--- a/app/services/issues/zoom_link_service.rb
+++ b/app/services/issues/zoom_link_service.rb
@@ -10,6 +10,7 @@ module Issues
def add_link(link)
if can_add_link? && (link = parse_link(link))
+ track_meeting_added_event
success(_('Zoom meeting added'), append_to_description(link))
else
error(_('Failed to add a Zoom meeting'))
@@ -22,6 +23,7 @@ module Issues
def remove_link
if can_remove_link?
+ track_meeting_removed_event
success(_('Zoom meeting removed'), remove_from_description)
else
error(_('Failed to remove a Zoom meeting'))
@@ -44,6 +46,14 @@ module Issues
issue.description || ''
end
+ def track_meeting_added_event
+ ::Gitlab::Tracking.event('IncidentManagement::ZoomIntegration', 'add_zoom_meeting', label: 'Issue ID', value: issue.id)
+ end
+
+ def track_meeting_removed_event
+ ::Gitlab::Tracking.event('IncidentManagement::ZoomIntegration', 'remove_zoom_meeting', label: 'Issue ID', value: issue.id)
+ end
+
def success(message, description)
ServiceResponse
.success(message: message, payload: { description: description })
diff --git a/app/views/clusters/clusters/cloud_providers/_cloud_provider_button.html.haml b/app/views/clusters/clusters/cloud_providers/_cloud_provider_button.html.haml
index f707c6585ec..d4999798c19 100644
--- a/app/views/clusters/clusters/cloud_providers/_cloud_provider_button.html.haml
+++ b/app/views/clusters/clusters/cloud_providers/_cloud_provider_button.html.haml
@@ -3,6 +3,6 @@
- label = local_assigns.fetch(:label)
= link_to clusterable.new_path(provider: provider), class: 'btn gl-button btn-outline flex-fill d-inline-flex flex-column mr-3 justify-content-center align-items-center' do
- = image_tag logo_path, alt: label, class: 'gl-w-13 gl-h-13'
+ .svg-content= image_tag logo_path, alt: label, class: 'gl-w-13 gl-h-13'
%span
= label
diff --git a/app/views/clusters/clusters/cloud_providers/_cloud_provider_selector.html.haml b/app/views/clusters/clusters/cloud_providers/_cloud_provider_selector.html.haml
index 24506205243..7a93a7604f5 100644
--- a/app/views/clusters/clusters/cloud_providers/_cloud_provider_selector.html.haml
+++ b/app/views/clusters/clusters/cloud_providers/_cloud_provider_selector.html.haml
@@ -6,6 +6,6 @@
= create_cluster_label
.d-flex
= render partial: 'clusters/clusters/cloud_providers/cloud_provider_button',
- locals: { provider: 'gke', label: gke_label, logo_path: '' }
+ locals: { provider: 'eks', label: eks_label, logo_path: 'illustrations/logos/amazon_eks.svg' }
= render partial: 'clusters/clusters/cloud_providers/cloud_provider_button',
- locals: { provider: 'eks', label: eks_label, logo_path: '' }
+ locals: { provider: 'gke', label: gke_label, logo_path: 'illustrations/logos/google_gke.svg' }
diff --git a/app/views/clusters/clusters/eks/_index.html.haml b/app/views/clusters/clusters/eks/_index.html.haml
index 0e9334948ab..db64698a7f2 100644
--- a/app/views/clusters/clusters/eks/_index.html.haml
+++ b/app/views/clusters/clusters/eks/_index.html.haml
@@ -1 +1,2 @@
-.js-create-eks-cluster-form-container{ data: { 'gitlab-managed-cluster-help-path' => help_page_path('user/project/clusters/index.md', anchor: 'gitlab-managed-clusters') } }
+.js-create-eks-cluster-form-container{ data: { 'gitlab-managed-cluster-help-path' => help_page_path('user/project/clusters/index.md', anchor: 'gitlab-managed-clusters'),
+'kubernetes-integration-help-path' => help_page_path('user/project/clusters/index') } }
diff --git a/app/views/clusters/clusters/gcp/_form.html.haml b/app/views/clusters/clusters/gcp/_form.html.haml
index 196ad422766..cca16ce7eda 100644
--- a/app/views/clusters/clusters/gcp/_form.html.haml
+++ b/app/views/clusters/clusters/gcp/_form.html.haml
@@ -3,13 +3,12 @@
- zones_link_url = 'https://cloud.google.com/compute/docs/regions-zones/regions-zones'
- machine_type_link_url = 'https://cloud.google.com/compute/docs/machine-types'
- pricing_link_url = 'https://cloud.google.com/compute/pricing#machinetype'
+- kubernetes_integration_url = help_page_path('user/project/clusters/index')
- help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe
- help_link_end = ' %{external_link_icon}</a>'.html_safe % { external_link_icon: external_link_icon }
%p
- - link_to_help_page = link_to(s_('ClusterIntegration|help page'),
- help_page_path('user/project/clusters/index'), target: '_blank', rel: 'noopener noreferrer')
- = s_('ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration.').html_safe % { link_to_help_page: link_to_help_page }
+ = s_('ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration.').html_safe % { link_start: help_link_start % { url: kubernetes_integration_url }, link_end: '</a>'.html_safe }
%p= link_to('Select a different Google account', @authorize_url)
diff --git a/app/views/clusters/clusters/gcp/_gcp_not_configured.html.haml b/app/views/clusters/clusters/gcp/_gcp_not_configured.html.haml
new file mode 100644
index 00000000000..b57e45e9812
--- /dev/null
+++ b/app/views/clusters/clusters/gcp/_gcp_not_configured.html.haml
@@ -0,0 +1,3 @@
+- documentation_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path("integration/google") }
+- link_end = '<a/>'.html_safe
+= s_('Google authentication is not %{link_start}property configured%{link_end}. Ask your GitLab administrator if you want to use this service.').html_safe % { link_start: documentation_link_start, link_end: link_end }
diff --git a/app/views/clusters/clusters/gcp/_signin_with_google_button.html.haml b/app/views/clusters/clusters/gcp/_signin_with_google_button.html.haml
new file mode 100644
index 00000000000..65cfa6552b1
--- /dev/null
+++ b/app/views/clusters/clusters/gcp/_signin_with_google_button.html.haml
@@ -0,0 +1,4 @@
+.signin-with-google
+ - create_account_link = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: 'https://accounts.google.com/SignUpWithoutGmail?service=cloudconsole&continue=https%3A%2F%2Fconsole.cloud.google.com%2Ffreetrial%3Futm_campaign%3D2018_cpanel%26utm_source%3Dgitlab%26utm_medium%3Dreferral' }
+ = link_to(image_tag('auth_buttons/signin_with_google.png', width: '191px', alt: _('Sign in with Google')), @authorize_url)
+ = s_('or %{link_start}create a new Google account%{link_end}').html_safe % { link_start: create_account_link, link_end: '</a>'.html_safe }
diff --git a/app/views/clusters/clusters/new.html.haml b/app/views/clusters/clusters/new.html.haml
index fb182d99ff0..2c23426aaf9 100644
--- a/app/views/clusters/clusters/new.html.haml
+++ b/app/views/clusters/clusters/new.html.haml
@@ -2,7 +2,9 @@
- page_title _('Kubernetes Cluster')
- create_eks_enabled = Feature.enabled?(:create_eks_clusters)
- active_tab = local_assigns.fetch(:active_tab, 'create')
-- link_end = '<a/>'.html_safe
+- create_on_gke_tab_label = s_('ClusterIntegration|Create new Cluster on GKE')
+- create_on_eks_tab_label = s_('ClusterIntegration|Create new Cluster on EKS')
+- create_new_cluster_label = s_('ClusterIntegration|Create new Cluster')
= javascript_include_tag 'https://apis.google.com/js/api.js'
= render_gcp_signup_offer
@@ -14,7 +16,16 @@
%ul.nav-links.nav-tabs.gitlab-tabs.nav{ role: 'tablist' }
%li.nav-item{ role: 'presentation' }
%a.nav-link{ href: '#create-cluster-pane', id: 'create-cluster-tab', class: active_when(active_tab == 'create'), data: { toggle: 'tab' }, role: 'tab' }
- %span Create new Cluster on GKE
+ %span
+ - if create_eks_enabled
+ - if @gke_selected
+ = create_on_gke_tab_label
+ - elsif @eks_selected
+ = create_on_eks_tab_label
+ - else
+ = create_new_cluster_label
+ - else
+ = create_on_gke_tab_label
%li.nav-item{ role: 'presentation' }
%a.nav-link{ href: '#add-cluster-pane', id: 'add-cluster-tab', class: active_when(active_tab == 'add'), data: { toggle: 'tab' }, role: 'tab' }
%span Add existing cluster
@@ -22,9 +33,14 @@
.tab-content.gitlab-tab-content
- if create_eks_enabled
.tab-pane{ id: 'create-cluster-pane', class: active_when(active_tab == 'create'), role: 'tabpanel' }
- - if @gke_selected && @valid_gcp_token
+ - if @gke_selected
= render 'clusters/clusters/gcp/header'
- = render 'clusters/clusters/gcp/form'
+ - if @valid_gcp_token
+ = render 'clusters/clusters/gcp/form'
+ - elsif @authorize_url
+ = render 'clusters/clusters/gcp/signin_with_google_button'
+ - else
+ = render 'clusters/clusters/gcp/gcp_not_configured'
- elsif @eks_selected
= render 'clusters/clusters/eks/index'
- else
@@ -35,13 +51,9 @@
- if @valid_gcp_token
= render 'clusters/clusters/gcp/form'
- elsif @authorize_url
- .signin-with-google
- - create_account_link = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: 'https://accounts.google.com/SignUpWithoutGmail?service=cloudconsole&continue=https%3A%2F%2Fconsole.cloud.google.com%2Ffreetrial%3Futm_campaign%3D2018_cpanel%26utm_source%3Dgitlab%26utm_medium%3Dreferral' }
- = link_to(image_tag('auth_buttons/signin_with_google.png', width: '191px', alt: _('Sign in with Google')), @authorize_url)
- = s_('or %{link_start}create a new Google account%{link_end}').html_safe % { link_start: create_account_link, link_end: link_end }
+ = render 'clusters/clusters/gcp/signin_with_google_button'
- else
- - documentation_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path("integration/google") }
- = s_('Google authentication is not %{link_start}property configured%{link_end}. Ask your GitLab administrator if you want to use this service.').html_safe % { link_start: documentation_link_start, link_end: link_end }
+ = render 'clusters/clusters/gcp/gcp_not_configured'
.tab-pane{ id: 'add-cluster-pane', class: active_when(active_tab == 'add'), role: 'tabpanel' }
= render 'clusters/clusters/user/header'
diff --git a/changelogs/unreleased/31923-Snowplow-custom-events-Monitor.yml b/changelogs/unreleased/31923-Snowplow-custom-events-Monitor.yml
new file mode 100644
index 00000000000..161fb59ca6e
--- /dev/null
+++ b/changelogs/unreleased/31923-Snowplow-custom-events-Monitor.yml
@@ -0,0 +1,5 @@
+---
+title: 'Snowplow custom events for Monitor: Health Product Categories'
+merge_request: 18157
+author:
+type: added
diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md
index 4152f31c726..d5749427f6e 100644
--- a/doc/administration/gitaly/index.md
+++ b/doc/administration/gitaly/index.md
@@ -549,7 +549,7 @@ a few things that you need to do:
1. Configure [database lookup of SSH keys](../operations/fast_ssh_key_lookup.md)
to eliminate the need for a shared authorized_keys file.
1. Configure [object storage for job artifacts](../job_artifacts.md#using-object-storage)
- including [live tracing](../job_traces.md#new-live-trace-architecture).
+ including [incremental logging](../job_logs.md#new-incremental-logging-architecture).
1. Configure [object storage for LFS objects](../../workflow/lfs/lfs_administration.md#storing-lfs-objects-in-remote-object-storage).
1. Configure [object storage for uploads](../uploads.md#using-object-storage-core-only).
diff --git a/doc/administration/index.md b/doc/administration/index.md
index fb6c1af991b..f90b9b2c7d5 100644
--- a/doc/administration/index.md
+++ b/doc/administration/index.md
@@ -154,7 +154,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [Enable/disable GitLab CI/CD](../ci/enable_or_disable_ci.md#site-wide-admin-setting): Enable or disable GitLab CI/CD for your instance.
- [GitLab CI/CD admin settings](../user/admin_area/settings/continuous_integration.md): Enable or disable Auto DevOps site-wide and define the artifacts' max size and expiration time.
- [Job artifacts](job_artifacts.md): Enable, disable, and configure job artifacts (a set of files and directories which are outputted by a job when it completes successfully).
-- [Job traces](job_traces.md): Information about the job traces (logs).
+- [Job logs](job_logs.md): Information about the job logs.
- [Register Shared and specific Runners](../ci/runners/README.md#registering-a-shared-runner): Learn how to register and configure Shared and specific Runners to your own instance.
- [Shared Runners pipelines quota](../user/admin_area/settings/continuous_integration.md#shared-runners-pipeline-minutes-quota-starter-only): Limit the usage of pipeline minutes for Shared Runners. **(STARTER ONLY)**
- [Enable/disable Auto DevOps](../topics/autodevops/index.md#enablingdisabling-auto-devops): Enable or disable Auto DevOps for your instance.
diff --git a/doc/administration/job_artifacts.md b/doc/administration/job_artifacts.md
index 86b18e673a5..ec2f40700f5 100644
--- a/doc/administration/job_artifacts.md
+++ b/doc/administration/job_artifacts.md
@@ -90,7 +90,7 @@ This configuration relies on valid AWS credentials to be configured already.
Use an object storage option like AWS S3 to store job artifacts.
DANGER: **Danger:**
-If you're enabling S3 in [GitLab HA](high_availability/README.md), you will need to have an [NFS mount set up for CI traces and artifacts](high_availability/nfs.md#a-single-nfs-mount) or enable [live tracing](job_traces.md#new-live-trace-architecture). If these settings are not set, you will risk job traces disappearing or not being saved.
+If you're enabling S3 in [GitLab HA](high_availability/README.md), you will need to have an [NFS mount set up for CI logs and artifacts](high_availability/nfs.md#a-single-nfs-mount) or enable [incremental logging](job_logs.md#new-incremental-logging-architecture). If these settings are not set, you will risk job logs disappearing or not being saved.
#### Object Storage Settings
diff --git a/doc/administration/job_logs.md b/doc/administration/job_logs.md
new file mode 100644
index 00000000000..d6d56515ac6
--- /dev/null
+++ b/doc/administration/job_logs.md
@@ -0,0 +1,169 @@
+# Job logs
+
+> [Renamed from Job Traces to Job logs](https://gitlab.com/gitlab-org/gitlab/issues/29121) in 12.4.
+
+Job logs (traces) are sent by GitLab Runner while it's processing a job. You can see
+logs in job pages, pipelines, email notifications, etc.
+
+## Data flow
+
+In general, there are two states for job logs: `log` and `archived log`.
+In the following table you can see the phases a log goes through:
+
+| Phase | State | Condition | Data flow | Stored path |
+| -------------- | ------------ | ----------------------- | -----------------------------------------| ----------- |
+| 1: patching | log | When a job is running | GitLab Runner => Unicorn => file storage | `#{ROOT_PATH}/gitlab-ci/builds/#{YYYY_mm}/#{project_id}/#{job_id}.log` |
+| 2: overwriting | log | When a job is finished | GitLab Runner => Unicorn => file storage | `#{ROOT_PATH}/gitlab-ci/builds/#{YYYY_mm}/#{project_id}/#{job_id}.log` |
+| 3: archiving | archived log | After a job is finished | Sidekiq moves log to artifacts folder | `#{ROOT_PATH}/gitlab-rails/shared/artifacts/#{disk_hash}/#{YYYY_mm_dd}/#{job_id}/#{job_artifact_id}/job.log` |
+| 4: uploading | archived log | After a log is archived | Sidekiq moves archived log to [object storage](#uploading-logs-to-object-storage) (if configured) | `#{bucket_name}/#{disk_hash}/#{YYYY_mm_dd}/#{job_id}/#{job_artifact_id}/job.log` |
+
+The `ROOT_PATH` varies per environment. For Omnibus GitLab it
+would be `/var/opt/gitlab`, and for installations from source
+it would be `/home/git/gitlab`.
+
+## Changing the job logs local location
+
+To change the location where the job logs will be stored, follow the steps below.
+
+**In Omnibus installations:**
+
+1. Edit `/etc/gitlab/gitlab.rb` and add or amend the following line:
+
+ ```ruby
+ gitlab_ci['builds_directory'] = '/mnt/to/gitlab-ci/builds'
+ ```
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+
+---
+
+**In installations from source:**
+
+1. Edit `/home/git/gitlab/config/gitlab.yml` and add or amend the following lines:
+
+ ```yaml
+ gitlab_ci:
+ # The location where build logs are stored (default: builds/).
+ # Relative paths are relative to Rails.root.
+ builds_path: path/to/builds/
+ ```
+
+1. Save the file and [restart GitLab][] for the changes to take effect.
+
+[reconfigure gitlab]: restart_gitlab.md#omnibus-gitlab-reconfigure "How to reconfigure Omnibus GitLab"
+[restart gitlab]: restart_gitlab.md#installations-from-source "How to restart GitLab"
+
+## Uploading logs to object storage
+
+Archived logs are considered as [job artifacts](job_artifacts.md).
+Therefore, when you [set up the object storage integration](job_artifacts.md#object-storage-settings),
+job logs are automatically migrated to it along with the other job artifacts.
+
+See "Phase 4: uploading" in [Data flow](#data-flow) to learn about the process.
+
+## How to remove job logs
+
+There isn't a way to automatically expire old job logs, but it's safe to remove
+them if they're taking up too much space. If you remove the logs manually, the
+job output in the UI will be empty.
+
+## New incremental logging architecture
+
+> [Introduced][ce-18169] in GitLab 10.4.
+> [Announced as General availability][ce-46097] in GitLab 11.0.
+
+NOTE: **Note:**
+This feature is off by default. See below for how to [enable or disable](#enabling-incremental-logging) it.
+
+By combining the process with object storage settings, we can completely bypass
+the local file storage. This is a useful option if GitLab is installed as
+cloud-native, for example on Kubernetes.
+
+The data flow is the same as described in the [data flow section](#data-flow)
+with one change: _the stored path of the first two phases is different_. This incremental
+log architecture stores chunks of logs in Redis and a persistent store (object storage or database) instead of
+file storage. Redis is used as first-class storage, and it stores up-to 128KB
+of data. Once the full chunk is sent, it is flushed to a persistent store, either object storage(temporary directory) or database.
+After a while, the data in Redis and a persitent store will be archived to [object storage](#uploading-logs-to-object-storage).
+
+The data are stored in the following Redis namespace: `Gitlab::Redis::SharedState`.
+
+Here is the detailed data flow:
+
+1. GitLab Runner picks a job from GitLab
+1. GitLab Runner sends a piece of log to GitLab
+1. GitLab appends the data to Redis
+1. Once the data in Redis reach 128KB, the data is flushed to a persistent store (object storage or the database).
+1. The above steps are repeated until the job is finished.
+1. Once the job is finished, GitLab schedules a Sidekiq worker to archive the log.
+1. The Sidekiq worker archives the log to object storage and cleans up the log
+ in Redis and a persistent store (object storage or the database).
+
+### Enabling incremental logging
+
+The following commands are to be issued in a Rails console:
+
+```sh
+# Omnibus GitLab
+gitlab-rails console
+
+# Installation from source
+cd /home/git/gitlab
+sudo -u git -H bin/rails console RAILS_ENV=production
+```
+
+**To check if incremental logging (trace) is enabled:**
+
+```ruby
+Feature.enabled?('ci_enable_live_trace')
+```
+
+**To enable incremental logging (trace):**
+
+```ruby
+Feature.enable('ci_enable_live_trace')
+```
+
+NOTE: **Note:**
+The transition period will be handled gracefully. Upcoming logs will be
+generated with the incremental architecture, and on-going logs will stay with the
+legacy architecture, which means that on-going logs won't be forcibly
+re-generated with the incremental architecture.
+
+**To disable incremental logging (trace):**
+
+```ruby
+Feature.disable('ci_enable_live_trace')
+```
+
+NOTE: **Note:**
+The transition period will be handled gracefully. Upcoming logs will be generated
+with the legacy architecture, and on-going incremental logs will stay with the incremental
+architecture, which means that on-going incremental logs won't be forcibly re-generated
+with the legacy architecture.
+
+### Potential implications
+
+In some cases, having data stored on Redis could incur data loss:
+
+1. **Case 1: When all data in Redis are accidentally flushed**
+ - On going incremental logs could be recovered by re-sending logs (this is
+ supported by all versions of the GitLab Runner).
+ - Finished jobs which have not archived incremental logs will lose the last part
+ (~128KB) of log data.
+
+1. **Case 2: When Sidekiq workers fail to archive (e.g., there was a bug that
+ prevents archiving process, Sidekiq inconsistency, etc.)**
+ - Currently all log data in Redis will be deleted after one week. If the
+ Sidekiq workers can't finish by the expiry date, the part of log data will be lost.
+
+Another issue that might arise is that it could consume all memory on the Redis
+instance. If the number of jobs is 1000, 128MB (128KB * 1000) is consumed.
+
+Also, it could pressure the database replication lag. `INSERT`s are generated to
+indicate that we have log chunk. `UPDATE`s with 128KB of data is issued once we
+receive multiple chunks.
+
+[ce-18169]: https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/18169
+[ce-21193]: https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/21193
+[ce-46097]: https://gitlab.com/gitlab-org/gitlab-foss/issues/46097
diff --git a/doc/administration/job_traces.md b/doc/administration/job_traces.md
index af60d777932..d0b346a931e 100644
--- a/doc/administration/job_traces.md
+++ b/doc/administration/job_traces.md
@@ -1,167 +1,5 @@
-# Job traces (logs)
-
-Job traces are sent by GitLab Runner while it's processing a job. You can see
-traces in job pages, pipelines, email notifications, etc.
-
-## Data flow
-
-In general, there are two states in job traces: "live trace" and "archived trace".
-In the following table you can see the phases a trace goes through.
-
-| Phase | State | Condition | Data flow | Stored path |
-| ----- | ----- | --------- | --------- | ----------- |
-| 1: patching | Live trace | When a job is running | GitLab Runner => Unicorn => file storage |`#{ROOT_PATH}/gitlab-ci/builds/#{YYYY_mm}/#{project_id}/#{job_id}.log`|
-| 2: overwriting | Live trace | When a job is finished | GitLab Runner => Unicorn => file storage |`#{ROOT_PATH}/gitlab-ci/builds/#{YYYY_mm}/#{project_id}/#{job_id}.log`|
-| 3: archiving | Archived trace | After a job is finished | Sidekiq moves live trace to artifacts folder |`#{ROOT_PATH}/gitlab-rails/shared/artifacts/#{disk_hash}/#{YYYY_mm_dd}/#{job_id}/#{job_artifact_id}/job.log`|
-| 4: uploading | Archived trace | After a trace is archived | Sidekiq moves archived trace to [object storage](#uploading-traces-to-object-storage) (if configured) |`#{bucket_name}/#{disk_hash}/#{YYYY_mm_dd}/#{job_id}/#{job_artifact_id}/job.log`|
-
-The `ROOT_PATH` varies per your environment. For Omnibus GitLab it
-would be `/var/opt/gitlab`, whereas for installations from source
-it would be `/home/git/gitlab`.
-
-## Changing the job traces local location
-
-To change the location where the job logs will be stored, follow the steps below.
-
-**In Omnibus installations:**
-
-1. Edit `/etc/gitlab/gitlab.rb` and add or amend the following line:
-
- ```ruby
- gitlab_ci['builds_directory'] = '/mnt/to/gitlab-ci/builds'
- ```
-
-1. Save the file and [reconfigure GitLab][] for the changes to take effect.
-
+---
+redirect_to: 'job_logs.md'
---
-**In installations from source:**
-
-1. Edit `/home/git/gitlab/config/gitlab.yml` and add or amend the following lines:
-
- ```yaml
- gitlab_ci:
- # The location where build traces are stored (default: builds/).
- # Relative paths are relative to Rails.root.
- builds_path: path/to/builds/
- ```
-
-1. Save the file and [restart GitLab][] for the changes to take effect.
-
-[reconfigure gitlab]: restart_gitlab.md#omnibus-gitlab-reconfigure "How to reconfigure Omnibus GitLab"
-[restart gitlab]: restart_gitlab.md#installations-from-source "How to restart GitLab"
-
-## Uploading traces to object storage
-
-Archived traces are considered as [job artifacts](job_artifacts.md).
-Therefore, when you [set up the object storage integration](job_artifacts.md#object-storage-settings),
-job traces are automatically migrated to it along with the other job artifacts.
-
-See "Phase 4: uploading" in [Data flow](#data-flow) to learn about the process.
-
-## How to remove job traces
-
-There isn't a way to automatically expire old job logs, but it's safe to remove
-them if they're taking up too much space. If you remove the logs manually, the
-job output in the UI will be empty.
-
-## New live trace architecture
-
-> [Introduced][ce-18169] in GitLab 10.4.
-> [Announced as General availability][ce-46097] in GitLab 11.0.
-
-NOTE: **Note:**
-This feature is off by default. Check below how to [enable/disable](#enabling-live-trace) it.
-
-By combining the process with object storage settings, we can completely bypass
-the local file storage. This is a useful option if GitLab is installed as
-cloud-native, for example on Kubernetes.
-
-The data flow is the same as described in the [data flow section](#data-flow)
-with one change: _the stored path of the first two phases is different_. This new live
-trace architecture stores chunks of traces in Redis and a persistent store (object storage or database) instead of
-file storage. Redis is used as first-class storage, and it stores up-to 128KB
-of data. Once the full chunk is sent, it is flushed a persistent store, either object storage(temporary directory) or database.
-After a while, the data in Redis and a persitent store will be archived to [object storage](#uploading-traces-to-object-storage).
-
-The data are stored in the following Redis namespace: `Gitlab::Redis::SharedState`.
-
-Here is the detailed data flow:
-
-1. GitLab Runner picks a job from GitLab
-1. GitLab Runner sends a piece of trace to GitLab
-1. GitLab appends the data to Redis
-1. Once the data in Redis reach 128KB, the data is flushed to a persistent store (object storage or the database).
-1. The above steps are repeated until the job is finished.
-1. Once the job is finished, GitLab schedules a Sidekiq worker to archive the trace.
-1. The Sidekiq worker archives the trace to object storage and cleans up the trace
- in Redis and a persistent store (object storage or the database).
-
-### Enabling live trace
-
-The following commands are to be issues in a Rails console:
-
-```sh
-# Omnibus GitLab
-gitlab-rails console
-
-# Installation from source
-cd /home/git/gitlab
-sudo -u git -H bin/rails console RAILS_ENV=production
-```
-
-**To check if live trace is enabled:**
-
-```ruby
-Feature.enabled?('ci_enable_live_trace')
-```
-
-**To enable live trace:**
-
-```ruby
-Feature.enable('ci_enable_live_trace')
-```
-
-NOTE: **Note:**
-The transition period will be handled gracefully. Upcoming traces will be
-generated with the new architecture, and on-going live traces will stay with the
-legacy architecture, which means that on-going live traces won't be forcibly
-re-generated with the new architecture.
-
-**To disable live trace:**
-
-```ruby
-Feature.disable('ci_enable_live_trace')
-```
-
-NOTE: **Note:**
-The transition period will be handled gracefully. Upcoming traces will be generated
-with the legacy architecture, and on-going live traces will stay with the new
-architecture, which means that on-going live traces won't be forcibly re-generated
-with the legacy architecture.
-
-### Potential implications
-
-In some cases, having data stored on Redis could incur data loss:
-
-1. **Case 1: When all data in Redis are accidentally flushed**
- - On going live traces could be recovered by re-sending traces (this is
- supported by all versions of the GitLab Runner).
- - Finished jobs which have not archived live traces will lose the last part
- (~128KB) of trace data.
-
-1. **Case 2: When Sidekiq workers fail to archive (e.g., there was a bug that
- prevents archiving process, Sidekiq inconsistency, etc.)**
- - Currently all trace data in Redis will be deleted after one week. If the
- Sidekiq workers can't finish by the expiry date, the part of trace data will be lost.
-
-Another issue that might arise is that it could consume all memory on the Redis
-instance. If the number of jobs is 1000, 128MB (128KB * 1000) is consumed.
-
-Also, it could pressure the database replication lag. `INSERT`s are generated to
-indicate that we have trace chunk. `UPDATE`s with 128KB of data is issued once we
-receive multiple chunks.
-
-[ce-18169]: https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/18169
-[ce-21193]: https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/21193
-[ce-46097]: https://gitlab.com/gitlab-org/gitlab-foss/issues/46097
+This document was moved to [another location](job_logs.md).
diff --git a/doc/api/jobs.md b/doc/api/jobs.md
index 8ee4facc018..bafcfd110d3 100644
--- a/doc/api/jobs.md
+++ b/doc/api/jobs.md
@@ -537,9 +537,9 @@ Possible response status codes:
| 400 | Invalid path provided |
| 404 | Build not found or no file/artifacts |
-## Get a trace file
+## Get a log file
-Get a trace of a specific job of a project
+Get a log (trace) of a specific job of a project:
```
GET /projects/:id/jobs/:job_id/trace
@@ -556,10 +556,10 @@ curl --location --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.ex
Possible response status codes:
-| Status | Description |
-|-----------|-----------------------------------|
-| 200 | Serves the trace file |
-| 404 | Build not found or no trace file |
+| Status | Description |
+|-----------|-------------------------------|
+| 200 | Serves the log file |
+| 404 | Job not found or no log file |
## Cancel a job
@@ -661,7 +661,7 @@ Example of response
## Erase a job
-Erase a single job of a project (remove job artifacts and a job trace)
+Erase a single job of a project (remove job artifacts and a job log)
```
POST /projects/:id/jobs/:job_id/erase
diff --git a/doc/ci/pipelines.md b/doc/ci/pipelines.md
index 0d0a40aceaa..e5f2701c6ae 100644
--- a/doc/ci/pipelines.md
+++ b/doc/ci/pipelines.md
@@ -283,11 +283,11 @@ You can also access pipelines for a merge request by navigating to its **Pipelin
When you access a pipeline, you can see the related jobs for that pipeline.
-Clicking on an individual job will show you its job trace, and allow you to:
+Clicking on an individual job will show you its job log, and allow you to:
- Cancel the job.
- Retry the job.
-- Erase the job trace.
+- Erase the job log.
### Seeing the failure reason for jobs
diff --git a/doc/ci/runners/README.md b/doc/ci/runners/README.md
index f7d1a3e88a2..4011ae4df70 100644
--- a/doc/ci/runners/README.md
+++ b/doc/ci/runners/README.md
@@ -365,8 +365,8 @@ We're always looking for contributions that can mitigate these
### Resetting the registration token for a Project
If you think that registration token for a Project was revealed, you should
-reset them. It's recommended because such token can be used to register another
-Runner to the Project. It may be next used to obtain the values of secret
+reset them. It's recommended because such a token can be used to register another
+Runner to the Project. It may then be used to obtain the values of secret
variables or clone the project code, that normally may be unavailable for the
attacker.
@@ -379,10 +379,10 @@ To reset the token:
1. After the page is refreshed, expand the **Runners settings** section
and check the registration token - it should be changed.
-From now on the old token is not valid anymore and will not allow to register
-a new Runner to the project. If you are using any tools to provision and
-register new Runners, you should now update the token that is used to the
-new value.
+From now on the old token is no longer valid and will not register
+any new Runners to the project. If you are using any tools to provision and
+register new Runners, the tokens used in those tools should be updated to reflect the
+value of the new token.
## Determining the IP address of a Runner
diff --git a/doc/ci/ssh_keys/README.md b/doc/ci/ssh_keys/README.md
index 64dc47f07cf..bee1501aed8 100644
--- a/doc/ci/ssh_keys/README.md
+++ b/doc/ci/ssh_keys/README.md
@@ -35,8 +35,8 @@ with any type of [executor](https://docs.gitlab.com/runner/executors/)
if you are accessing a private GitLab repository.
NOTE: **Note:**
-The private key will not be displayed in the job trace, unless you enable
-[debug tracing](../variables/README.md#debug-tracing). You might also want to
+The private key will not be displayed in the job log, unless you enable
+[debug logging](../variables/README.md#debug-logging). You might also want to
check the [visibility of your pipelines](../../user/project/pipelines/settings.md#visibility-of-pipelines).
## SSH keys when using the Docker executor
diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md
index 34e5bcd9601..5d86d382aa8 100644
--- a/doc/ci/variables/README.md
+++ b/doc/ci/variables/README.md
@@ -568,7 +568,7 @@ Below you can find supported syntax reference:
Precedence of operators follows standard Ruby 2.5 operation
[precedence](https://ruby-doc.org/core-2.5.0/doc/syntax/precedence_rdoc.html).
-## Debug tracing
+## Debug logging
> Introduced in GitLab Runner 1.7.
@@ -576,24 +576,24 @@ CAUTION: **Warning:**
Enabling debug tracing can have severe security implications. The
output **will** contain the content of all your variables and any other
secrets! The output **will** be uploaded to the GitLab server and made visible
-in job traces!
+in job logs!
By default, GitLab Runner hides most of the details of what it is doing when
-processing a job. This behavior keeps job traces short, and prevents secrets
-from being leaked into the trace unless your script writes them to the screen.
+processing a job. This behavior keeps job logs short, and prevents secrets
+from being leaked into the log unless your script writes them to the screen.
If a job isn't working as expected, this can make the problem difficult to
investigate; in these cases, you can enable debug tracing in `.gitlab-ci.yml`.
Available on GitLab Runner v1.7+, this feature enables the shell's execution
-trace, resulting in a verbose job trace listing all commands that were run,
+log, resulting in a verbose job log listing all commands that were run,
variables that were set, etc.
Before enabling this, you should ensure jobs are visible to
[team members only](../../user/permissions.md#project-features). You should
-also [erase](../pipelines.md#accessing-individual-jobs) all generated job traces
+also [erase](../pipelines.md#accessing-individual-jobs) all generated job logs
before making them visible again.
-To enable debug traces, set the `CI_DEBUG_TRACE` variable to `true`:
+To enable debug logs (traces), set the `CI_DEBUG_TRACE` variable to `true`:
```yaml
job_name:
@@ -601,7 +601,7 @@ job_name:
CI_DEBUG_TRACE: "true"
```
-Example truncated output with debug trace set to true:
+Example truncated output with `CI_DEBUG_TRACE` set to `true`:
```bash
...
diff --git a/doc/ci/variables/predefined_variables.md b/doc/ci/variables/predefined_variables.md
index 52f712abfae..9a27650532f 100644
--- a/doc/ci/variables/predefined_variables.md
+++ b/doc/ci/variables/predefined_variables.md
@@ -40,7 +40,7 @@ future GitLab releases.**
| `CI_COMMIT_TAG` | 9.0 | 0.5 | The commit tag name. Present only when building tags. |
| `CI_COMMIT_TITLE` | 10.8 | all | The title of the commit - the full first line of the message |
| `CI_CONFIG_PATH` | 9.4 | 0.5 | The path to CI config file. Defaults to `.gitlab-ci.yml` |
-| `CI_DEBUG_TRACE` | all | 1.7 | Whether [debug tracing](README.md#debug-tracing) is enabled |
+| `CI_DEBUG_TRACE` | all | 1.7 | Whether [debug logging (tracing)](README.md#debug-logging) is enabled |
| `CI_DEPLOY_PASSWORD` | 10.8 | all | Authentication password of the [GitLab Deploy Token][gitlab-deploy-token], only present if the Project has one related.|
| `CI_DEPLOY_USER` | 10.8 | all | Authentication username of the [GitLab Deploy Token][gitlab-deploy-token], only present if the Project has one related.|
| `CI_DISPOSABLE_ENVIRONMENT` | all | 10.1 | Marks that the job is executed in a disposable environment (something that is created only for this job and disposed of/destroyed after the execution - all executors except `shell` and `ssh`). If the environment is disposable, it is set to true, otherwise it is not defined at all. |
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index 41fdfa6557a..38687c6e6e2 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -242,7 +242,7 @@ For more information, see see [Available settings for `services`](../docker/usin
`before_script` is used to define the command that should be run before all
jobs, including deploy jobs, but after the restoration of [artifacts](#artifacts).
-This can be an array or a multi-line string.
+This must be an an array.
`after_script` is used to define the command that will be run after all
jobs, including failed ones. This has to be an array or a multi-line string.
diff --git a/doc/install/installation.md b/doc/install/installation.md
index ed0997f86a6..dd4b5544659 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -448,7 +448,7 @@ sudo -u git -H mkdir -p public/uploads/
# now that files in public/uploads are served by gitlab-workhorse
sudo chmod 0700 public/uploads
-# Change the permissions of the directory where CI job traces are stored
+# Change the permissions of the directory where CI job logs are stored
sudo chmod -R u+rwX builds/
# Change the permissions of the directory where CI artifacts are stored
diff --git a/doc/user/group/saml_sso/index.md b/doc/user/group/saml_sso/index.md
index d40ddb00390..ecf2934b877 100644
--- a/doc/user/group/saml_sso/index.md
+++ b/doc/user/group/saml_sso/index.md
@@ -113,6 +113,25 @@ NOTE: **Note:** GitLab is unable to provide support for IdPs that are not listed
| OneLogin | [Use the OneLogin SAML Test Connector](https://onelogin.service-now.com/support?id=kb_article&sys_id=93f95543db109700d5505eea4b96198f) |
| Ping Identity | [Add and configure a new SAML application](https://support.pingidentity.com/s/document-item?bundleId=pingone&topicId=xsh1564020480660-1.html) |
+When [configuring your identify provider](#configuring-your-identity-provider), please consider the notes below for specific providers to help avoid common issues and as a guide for terminology used.
+
+### OneLogin setup notes
+
+NOTE: **Note:**
+The GitLab app listed in the directory is for self-managed GitLab instances. Please use a generic SAML Test Connector.
+
+| GitLab Setting | OneLogin Field |
+|--------------|----------------|
+| Identifier | Audience |
+| Assertion consumer service URL | Recipient |
+| Assertion consumer service URL | ACS (Consumer) URL |
+| Assertion consumer service URL (escaped version) | ACS (Consumer) URL Validator |
+| GitLab single sign on URL | Login URL |
+
+Recommended `NameID` value: `OneLogin ID`.
+
+Set parameters according to the [assertions table](#assertions).
+
## Linking SAML to your existing GitLab.com account
To link SAML to your existing GitLab.com account:
diff --git a/lib/gitlab/gitaly_client/conflict_files_stitcher.rb b/lib/gitlab/gitaly_client/conflict_files_stitcher.rb
index 0e00f6e8c44..38ec910111c 100644
--- a/lib/gitlab/gitaly_client/conflict_files_stitcher.rb
+++ b/lib/gitlab/gitaly_client/conflict_files_stitcher.rb
@@ -5,8 +5,11 @@ module Gitlab
class ConflictFilesStitcher
include Enumerable
- def initialize(rpc_response)
+ attr_reader :gitaly_repo
+
+ def initialize(rpc_response, gitaly_repo)
@rpc_response = rpc_response
+ @gitaly_repo = gitaly_repo
end
def each
@@ -31,7 +34,7 @@ module Gitlab
def file_from_gitaly_header(header)
Gitlab::Git::Conflict::File.new(
- Gitlab::GitalyClient::Util.git_repository(header.repository),
+ Gitlab::GitalyClient::Util.git_repository(gitaly_repo),
header.commit_oid,
conflict_from_gitaly_file_header(header),
''
diff --git a/lib/gitlab/gitaly_client/conflicts_service.rb b/lib/gitlab/gitaly_client/conflicts_service.rb
index c497bd12738..f7eb4b45197 100644
--- a/lib/gitlab/gitaly_client/conflicts_service.rb
+++ b/lib/gitlab/gitaly_client/conflicts_service.rb
@@ -22,7 +22,7 @@ module Gitlab
)
response = GitalyClient.call(@repository.storage, :conflicts_service, :list_conflict_files, request, timeout: GitalyClient.long_timeout)
- GitalyClient::ConflictFilesStitcher.new(response)
+ GitalyClient::ConflictFilesStitcher.new(response, @gitaly_repo)
end
def conflicts?
diff --git a/lib/gitlab/tracking/incident_management.rb b/lib/gitlab/tracking/incident_management.rb
new file mode 100644
index 00000000000..bd8d1669dd3
--- /dev/null
+++ b/lib/gitlab/tracking/incident_management.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Tracking
+ module IncidentManagement
+ class << self
+ def track_from_params(incident_params)
+ return if incident_params.blank?
+
+ incident_params.each do |k, v|
+ prefix = ['', '0'].include?(v.to_s) ? 'disabled' : 'enabled'
+
+ key = tracking_keys.dig(k, :name)
+ label = tracking_keys.dig(k, :label)
+
+ next if key.blank?
+
+ details = label ? { label: label, property: v } : {}
+
+ ::Gitlab::Tracking.event('IncidentManagement::Settings', "#{prefix}_#{key}", **details )
+ end
+ end
+
+ def tracking_keys
+ {
+ create_issue: {
+ name: 'issue_auto_creation_on_alerts'
+ },
+ issue_template_key: {
+ name: 'issue_template_on_alerts',
+ label: 'Template name'
+ },
+ send_email: {
+ name: 'sending_emails'
+ }
+ }.with_indifferent_access.freeze
+ end
+ end
+ end
+ end
+end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index d760d993762..640e9c5f3b8 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -3528,6 +3528,15 @@ msgstr ""
msgid "ClusterIntegration|Create cluster on"
msgstr ""
+msgid "ClusterIntegration|Create new Cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Create new Cluster on EKS"
+msgstr ""
+
+msgid "ClusterIntegration|Create new Cluster on GKE"
+msgstr ""
+
msgid "ClusterIntegration|Did you know?"
msgstr ""
@@ -3540,6 +3549,9 @@ msgstr ""
msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
msgstr ""
+msgid "ClusterIntegration|Enter the details for your Amazon EKS Kubernetes cluster"
+msgstr ""
+
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
msgstr ""
@@ -3801,7 +3813,7 @@ msgstr ""
msgid "ClusterIntegration|RBAC-enabled cluster"
msgstr ""
-msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
+msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr ""
msgid "ClusterIntegration|Region"
@@ -4017,9 +4029,6 @@ msgstr ""
msgid "ClusterIntegration|documentation"
msgstr ""
-msgid "ClusterIntegration|help page"
-msgstr ""
-
msgid "ClusterIntegration|installed via %{installed_via}"
msgstr ""
diff --git a/spec/features/projects/clusters/eks_spec.rb b/spec/features/projects/clusters/eks_spec.rb
new file mode 100644
index 00000000000..758dccd6e49
--- /dev/null
+++ b/spec/features/projects/clusters/eks_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'AWS EKS Cluster', :js do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_maintainer(user)
+ gitlab_sign_in(user)
+ allow(Projects::ClustersController).to receive(:STATUS_POLLING_INTERVAL) { 100 }
+ end
+
+ context 'when user does not have a cluster and visits cluster index page' do
+ let(:project_id) { 'test-project-1234' }
+
+ before do
+ visit project_clusters_path(project)
+
+ click_link 'Add Kubernetes cluster'
+ end
+
+ context 'when user creates a cluster on AWS EKS' do
+ before do
+ click_link 'Amazon EKS'
+ end
+
+ it 'user sees a form to create an EKS cluster' do
+ expect(page).to have_selector(:css, '.js-create-eks-cluster')
+ end
+ end
+ end
+end
diff --git a/spec/features/projects/clusters/gcp_spec.rb b/spec/features/projects/clusters/gcp_spec.rb
index a11237db508..b5ab9faa14b 100644
--- a/spec/features/projects/clusters/gcp_spec.rb
+++ b/spec/features/projects/clusters/gcp_spec.rb
@@ -177,6 +177,7 @@ describe 'Gcp Cluster', :js do
context 'when user has not dismissed GCP signup offer' do
before do
+ stub_feature_flags(create_eks_clusters: false)
visit project_clusters_path(project)
end
@@ -200,6 +201,7 @@ describe 'Gcp Cluster', :js do
context 'when user has dismissed GCP signup offer' do
before do
+ stub_feature_flags(create_eks_clusters: false)
visit project_clusters_path(project)
end
diff --git a/spec/features/projects/clusters_spec.rb b/spec/features/projects/clusters_spec.rb
index d1cd19dff2d..67d14d0a58a 100644
--- a/spec/features/projects/clusters_spec.rb
+++ b/spec/features/projects/clusters_spec.rb
@@ -74,7 +74,7 @@ describe 'Clusters', :js do
visit project_clusters_path(project)
click_link 'Add Kubernetes cluster'
- click_link 'Create new Cluster on GKE'
+ click_link 'Create new Cluster'
end
it 'user sees a link to create a GKE cluster' do
diff --git a/spec/frontend/create_cluster/eks_cluster/components/eks_cluster_configuration_form_spec.js b/spec/frontend/create_cluster/eks_cluster/components/eks_cluster_configuration_form_spec.js
index 321dc5bd6ba..69290f6dfa9 100644
--- a/spec/frontend/create_cluster/eks_cluster/components/eks_cluster_configuration_form_spec.js
+++ b/spec/frontend/create_cluster/eks_cluster/components/eks_cluster_configuration_form_spec.js
@@ -123,6 +123,7 @@ describe('EksClusterConfigurationForm', () => {
store,
propsData: {
gitlabManagedClusterHelpPath: '',
+ kubernetesIntegrationHelpPath: '',
},
});
});
diff --git a/spec/frontend/error_tracking/utils_spec.js b/spec/frontend/error_tracking/utils_spec.js
new file mode 100644
index 00000000000..0e9047cd375
--- /dev/null
+++ b/spec/frontend/error_tracking/utils_spec.js
@@ -0,0 +1,27 @@
+import * as errorTrackingUtils from '~/error_tracking/utils';
+
+const externalUrl = 'https://sentry.io/organizations/test-sentry-nk/issues/1/?project=1';
+
+describe('Error Tracking Events', () => {
+ describe('trackViewInSentryOptions', () => {
+ it('should return correct event options', () => {
+ expect(errorTrackingUtils.trackViewInSentryOptions(externalUrl)).toEqual({
+ category: 'Error Tracking',
+ action: 'click_view_in_sentry',
+ label: 'External Url',
+ property: externalUrl,
+ });
+ });
+ });
+
+ describe('trackClickErrorLinkToSentryOptions', () => {
+ it('should return correct event options', () => {
+ expect(errorTrackingUtils.trackClickErrorLinkToSentryOptions(externalUrl)).toEqual({
+ category: 'Error Tracking',
+ action: 'click_error_link_to_sentry',
+ label: 'Error Link',
+ property: externalUrl,
+ });
+ });
+ });
+});
diff --git a/spec/frontend/monitoring/utils_spec.js b/spec/frontend/monitoring/utils_spec.js
new file mode 100644
index 00000000000..1e8d5753885
--- /dev/null
+++ b/spec/frontend/monitoring/utils_spec.js
@@ -0,0 +1,54 @@
+import * as monitoringUtils from '~/monitoring/utils';
+
+describe('Snowplow Events', () => {
+ const generatedLink = 'http://chart.link.com';
+ const chartTitle = 'Some metric chart';
+
+ describe('trackGenerateLinkToChartEventOptions', () => {
+ it('should return Cluster Monitoring options if located on Cluster Health Dashboard', () => {
+ document.body.dataset.page = 'groups:clusters:show';
+
+ expect(monitoringUtils.generateLinkToChartOptions(generatedLink)).toEqual({
+ category: 'Cluster Monitoring',
+ action: 'generate_link_to_cluster_metric_chart',
+ label: 'Chart link',
+ property: generatedLink,
+ });
+ });
+
+ it('should return Incident Management event options if located on Metrics Dashboard', () => {
+ document.body.dataset.page = 'metrics:show';
+
+ expect(monitoringUtils.generateLinkToChartOptions(generatedLink)).toEqual({
+ category: 'Incident Management::Embedded metrics',
+ action: 'generate_link_to_metrics_chart',
+ label: 'Chart link',
+ property: generatedLink,
+ });
+ });
+ });
+
+ describe('trackDownloadCSVEvent', () => {
+ it('should return Cluster Monitoring options if located on Cluster Health Dashboard', () => {
+ document.body.dataset.page = 'groups:clusters:show';
+
+ expect(monitoringUtils.downloadCSVOptions(chartTitle)).toEqual({
+ category: 'Cluster Monitoring',
+ action: 'download_csv_of_cluster_metric_chart',
+ label: 'Chart title',
+ property: chartTitle,
+ });
+ });
+
+ it('should return Incident Management event options if located on Metrics Dashboard', () => {
+ document.body.dataset.page = 'metriss:show';
+
+ expect(monitoringUtils.downloadCSVOptions(chartTitle)).toEqual({
+ category: 'Incident Management::Embedded metrics',
+ action: 'download_csv_of_metrics_dashboard_chart',
+ label: 'Chart title',
+ property: chartTitle,
+ });
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/directives/track_event_spec.js b/spec/frontend/vue_shared/directives/track_event_spec.js
new file mode 100644
index 00000000000..d63f6ae05b4
--- /dev/null
+++ b/spec/frontend/vue_shared/directives/track_event_spec.js
@@ -0,0 +1,49 @@
+import Vue from 'vue';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import Tracking from '~/tracking';
+import TrackEvent from '~/vue_shared/directives/track_event';
+
+jest.mock('~/tracking');
+
+const Component = Vue.component('dummy-element', {
+ directives: {
+ TrackEvent,
+ },
+ data() {
+ return {
+ trackingOptions: null,
+ };
+ },
+ template: '<button id="trackable" v-track-event="trackingOptions"></button>',
+});
+
+const localVue = createLocalVue();
+let wrapper;
+let button;
+
+describe('Error Tracking directive', () => {
+ beforeEach(() => {
+ wrapper = shallowMount(localVue.extend(Component), {
+ localVue,
+ });
+ button = wrapper.find('#trackable');
+ });
+
+ it('should not track the event if required arguments are not provided', () => {
+ button.trigger('click');
+ expect(Tracking.event).not.toHaveBeenCalled();
+ });
+
+ it('should track event on click if tracking info provided', () => {
+ const trackingOptions = {
+ category: 'Tracking',
+ action: 'click_trackable_btn',
+ label: 'Trackable Info',
+ };
+
+ wrapper.setData({ trackingOptions });
+ const { category, action, label, property, value } = trackingOptions;
+ button.trigger('click');
+ expect(Tracking.event).toHaveBeenCalledWith(category, action, { label, property, value });
+ });
+});
diff --git a/spec/lib/gitlab/gitaly_client/conflict_files_stitcher_spec.rb b/spec/lib/gitlab/gitaly_client/conflict_files_stitcher_spec.rb
index 1c933410bd5..a3602463756 100644
--- a/spec/lib/gitlab/gitaly_client/conflict_files_stitcher_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/conflict_files_stitcher_spec.rb
@@ -32,7 +32,7 @@ describe Gitlab::GitalyClient::ConflictFilesStitcher do
double(files: [double(header: nil, content: content_2[11..-1])])
]
- conflict_files = described_class.new(messages).to_a
+ conflict_files = described_class.new(messages, target_repository.gitaly_repository).to_a
expect(conflict_files.size).to be(2)
diff --git a/spec/lib/gitlab/tracking/incident_management_spec.rb b/spec/lib/gitlab/tracking/incident_management_spec.rb
new file mode 100644
index 00000000000..6f7e04b7c16
--- /dev/null
+++ b/spec/lib/gitlab/tracking/incident_management_spec.rb
@@ -0,0 +1,78 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Tracking::IncidentManagement do
+ describe '.track_from_params' do
+ shared_examples 'a tracked event' do |label, value = nil|
+ it 'creates the tracking event with the correct details' do
+ expect(::Gitlab::Tracking)
+ .to receive(:event)
+ .with(
+ 'IncidentManagement::Settings',
+ label,
+ value || kind_of(Hash)
+ )
+ end
+ end
+
+ after do
+ described_class.track_from_params(params)
+ end
+
+ context 'known params' do
+ known_params = described_class.tracking_keys
+
+ known_params.each do |key, values|
+ context "param #{key}" do
+ let(:params) { { key => '1' } }
+
+ it_behaves_like 'a tracked event', "enabled_#{known_params[key][:name]}"
+ end
+ end
+
+ context 'different input values' do
+ shared_examples 'the correct prefixed event name' do |input, enabled|
+ let(:params) { { issue_template_key: input } }
+
+ it 'matches' do
+ expect(::Gitlab::Tracking)
+ .to receive(:event)
+ .with(
+ anything,
+ "#{enabled}_issue_template_on_alerts",
+ anything
+ )
+ end
+ end
+
+ it_behaves_like 'the correct prefixed event name', 1, 'enabled'
+ it_behaves_like 'the correct prefixed event name', '1', 'enabled'
+ it_behaves_like 'the correct prefixed event name', 'template', 'enabled'
+ it_behaves_like 'the correct prefixed event name', '', 'disabled'
+ it_behaves_like 'the correct prefixed event name', nil, 'disabled'
+ end
+
+ context 'param with label' do
+ let(:params) { { issue_template_key: '1' } }
+
+ it_behaves_like 'a tracked event', "enabled_issue_template_on_alerts", { label: 'Template name', property: '1' }
+ end
+
+ context 'param without label' do
+ let(:params) { { create_issue: '1' } }
+
+ it_behaves_like 'a tracked event', "enabled_issue_auto_creation_on_alerts", {}
+ end
+ end
+
+ context 'unknown params' do
+ let(:params) { { 'unknown' => '1' } }
+
+ it 'does not create the tracking event' do
+ expect(::Gitlab::Tracking)
+ .not_to receive(:event)
+ end
+ end
+ end
+end
diff --git a/spec/services/issues/zoom_link_service_spec.rb b/spec/services/issues/zoom_link_service_spec.rb
index 595d06d5331..ba3f007c917 100644
--- a/spec/services/issues/zoom_link_service_spec.rb
+++ b/spec/services/issues/zoom_link_service_spec.rb
@@ -51,6 +51,12 @@ describe Issues::ZoomLinkService do
expect(result.payload[:description])
.to eq("#{issue.description}\n\n#{zoom_link}")
end
+
+ it 'tracks the add event' do
+ expect(Gitlab::Tracking).to receive(:event)
+ .with('IncidentManagement::ZoomIntegration', 'add_zoom_meeting', label: 'Issue ID', value: issue.id)
+ result
+ end
end
shared_examples 'cannot add link' do
@@ -135,6 +141,13 @@ describe Issues::ZoomLinkService do
.to eq(issue.description.delete_suffix("\n\n#{zoom_link}"))
end
+ it 'tracks the remove event' do
+ expect(Gitlab::Tracking).to receive(:event)
+ .with('IncidentManagement::ZoomIntegration', 'remove_zoom_meeting', label: 'Issue ID', value: issue.id)
+
+ result
+ end
+
context 'with insufficient permissions' do
include_context 'insufficient permissions'
include_examples 'cannot remove link'