Commit 99ebbe65 authored by Sean Arnold's avatar Sean Arnold Committed by Peter Hegman

Disallow integrated error tracking by default

Introduce feature flag. Hide UI and prevent API calls

Changelog: changed
parent e0f5dc24
...@@ -26,7 +26,7 @@ import { ...@@ -26,7 +26,7 @@ import {
trackErrorStatusUpdateOptions, trackErrorStatusUpdateOptions,
} from '../utils'; } from '../utils';
import { severityLevel, severityLevelVariant, errorStatus } from './constants'; import { severityLevel, severityLevelVariant, errorStatus } from '../constants';
import Stacktrace from './stacktrace.vue'; import Stacktrace from './stacktrace.vue';
const SENTRY_TIMEOUT = 10000; const SENTRY_TIMEOUT = 10000;
......
<script> <script>
import { import {
GlAlert,
GlEmptyState, GlEmptyState,
GlButton, GlButton,
GlIcon, GlIcon,
...@@ -10,6 +11,7 @@ import { ...@@ -10,6 +11,7 @@ import {
GlDropdown, GlDropdown,
GlDropdownItem, GlDropdownItem,
GlDropdownDivider, GlDropdownDivider,
GlSprintf,
GlTooltipDirective, GlTooltipDirective,
GlPagination, GlPagination,
} from '@gitlab/ui'; } from '@gitlab/ui';
...@@ -21,6 +23,7 @@ import { __ } from '~/locale'; ...@@ -21,6 +23,7 @@ import { __ } from '~/locale';
import Tracking from '~/tracking'; import Tracking from '~/tracking';
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue'; import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
import { trackErrorListViewsOptions, trackErrorStatusUpdateOptions } from '../utils'; import { trackErrorListViewsOptions, trackErrorStatusUpdateOptions } from '../utils';
import { I18N_ERROR_TRACKING_LIST } from '../constants';
import ErrorTrackingActions from './error_tracking_actions.vue'; import ErrorTrackingActions from './error_tracking_actions.vue';
export const tableDataClass = 'table-col d-flex d-md-table-cell align-items-center'; export const tableDataClass = 'table-col d-flex d-md-table-cell align-items-center';
...@@ -29,6 +32,7 @@ export default { ...@@ -29,6 +32,7 @@ export default {
FIRST_PAGE: 1, FIRST_PAGE: 1,
PREV_PAGE: 1, PREV_PAGE: 1,
NEXT_PAGE: 2, NEXT_PAGE: 2,
i18n: I18N_ERROR_TRACKING_LIST,
fields: [ fields: [
{ {
key: 'error', key: 'error',
...@@ -71,6 +75,7 @@ export default { ...@@ -71,6 +75,7 @@ export default {
frequency: __('Frequency'), frequency: __('Frequency'),
}, },
components: { components: {
GlAlert,
GlEmptyState, GlEmptyState,
GlButton, GlButton,
GlDropdown, GlDropdown,
...@@ -81,6 +86,7 @@ export default { ...@@ -81,6 +86,7 @@ export default {
GlLoadingIcon, GlLoadingIcon,
GlTable, GlTable,
GlFormInput, GlFormInput,
GlSprintf,
GlPagination, GlPagination,
TimeAgo, TimeAgo,
ErrorTrackingActions, ErrorTrackingActions,
...@@ -117,12 +123,17 @@ export default { ...@@ -117,12 +123,17 @@ export default {
type: String, type: String,
required: true, required: true,
}, },
showIntegratedTrackingDisabledAlert: {
type: Boolean,
required: false,
},
}, },
hasLocalStorage: AccessorUtils.canUseLocalStorage(), hasLocalStorage: AccessorUtils.canUseLocalStorage(),
data() { data() {
return { return {
errorSearchQuery: '', errorSearchQuery: '',
pageValue: this.$options.FIRST_PAGE, pageValue: this.$options.FIRST_PAGE,
isAlertDismissed: false,
}; };
}, },
computed: { computed: {
...@@ -142,6 +153,9 @@ export default { ...@@ -142,6 +153,9 @@ export default {
errorTrackingHelpUrl() { errorTrackingHelpUrl() {
return helpPagePath('operations/error_tracking'); return helpPagePath('operations/error_tracking');
}, },
showIntegratedDisabledAlert() {
return !this.isAlertDismissed && this.showIntegratedTrackingDisabledAlert;
},
}, },
watch: { watch: {
pagination() { pagination() {
...@@ -150,6 +164,8 @@ export default { ...@@ -150,6 +164,8 @@ export default {
} }
}, },
}, },
epicLink: 'https://gitlab.com/gitlab-org/gitlab/-/issues/353639',
featureFlagLink: helpPagePath('operations/error_tracking'),
created() { created() {
if (this.errorTrackingEnabled) { if (this.errorTrackingEnabled) {
this.setEndpoint(this.indexPath); this.setEndpoint(this.indexPath);
...@@ -232,6 +248,34 @@ export default { ...@@ -232,6 +248,34 @@ export default {
<template> <template>
<div class="error-list"> <div class="error-list">
<div v-if="errorTrackingEnabled"> <div v-if="errorTrackingEnabled">
<gl-alert
v-if="showIntegratedDisabledAlert"
variant="danger"
data-testid="integrated-disabled-alert"
@dismiss="isAlertDismissed = true"
>
<gl-sprintf :message="this.$options.i18n.integratedErrorTrackingDisabledText">
<template #epicLink="{ content }">
<gl-link :href="$options.epicLink" target="_blank">{{ content }}</gl-link>
</template>
<template #flagLink="{ content }">
<gl-link :href="$options.featureFlagLink" target="_blank">{{ content }}</gl-link>
</template>
<template #settingsLink="{ content }">
<gl-link :href="enableErrorTrackingLink" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
<div>
<gl-button
category="primary"
variant="confirm"
:href="enableErrorTrackingLink"
class="gl-mr-auto gl-mt-3"
>
{{ $options.i18n.viewProjectSettingsButton }}
</gl-button>
</div>
</gl-alert>
<div <div
class="row flex-column flex-md-row align-items-md-center m-0 mt-sm-2 p-3 p-sm-3 bg-secondary border" class="row flex-column flex-md-row align-items-md-center m-0 mt-sm-2 p-3 p-sm-3 bg-secondary border"
> >
......
import { s__ } from '~/locale';
export const severityLevel = { export const severityLevel = {
FATAL: 'fatal', FATAL: 'fatal',
ERROR: 'error', ERROR: 'error',
...@@ -19,3 +21,10 @@ export const errorStatus = { ...@@ -19,3 +21,10 @@ export const errorStatus = {
RESOLVED: 'resolved', RESOLVED: 'resolved',
UNRESOLVED: 'unresolved', UNRESOLVED: 'unresolved',
}; };
export const I18N_ERROR_TRACKING_LIST = {
integratedErrorTrackingDisabledText: s__(
'ErrorTracking|Integrated error tracking is %{epicLinkStart}turned off by default%{epicLinkEnd} and no longer active for this project. To re-enable error tracking on self-hosted instances, you can either %{flagLinkStart}turn on the feature flag%{flagLinkEnd} for integrated error tracking, or provide a %{settingsLinkStart}Sentry API URL and Auth Token%{settingsLinkEnd} on your project settings page. However, error tracking is not ready for production use and cannot be enabled on GitLab.com.',
),
viewProjectSettingsButton: s__('ErrorTracking|View project settings'),
};
...@@ -14,10 +14,15 @@ export default () => { ...@@ -14,10 +14,15 @@ export default () => {
projectPath, projectPath,
listPath, listPath,
} = domEl.dataset; } = domEl.dataset;
let { errorTrackingEnabled, userCanEnableErrorTracking } = domEl.dataset; let {
errorTrackingEnabled,
userCanEnableErrorTracking,
showIntegratedTrackingDisabledAlert,
} = domEl.dataset;
errorTrackingEnabled = parseBoolean(errorTrackingEnabled); errorTrackingEnabled = parseBoolean(errorTrackingEnabled);
userCanEnableErrorTracking = parseBoolean(userCanEnableErrorTracking); userCanEnableErrorTracking = parseBoolean(userCanEnableErrorTracking);
showIntegratedTrackingDisabledAlert = parseBoolean(showIntegratedTrackingDisabledAlert);
// eslint-disable-next-line no-new // eslint-disable-next-line no-new
new Vue({ new Vue({
...@@ -36,6 +41,7 @@ export default () => { ...@@ -36,6 +41,7 @@ export default () => {
userCanEnableErrorTracking, userCanEnableErrorTracking,
projectPath, projectPath,
listPath, listPath,
showIntegratedTrackingDisabledAlert,
}, },
}); });
}, },
......
<script> <script>
import { import {
GlAlert,
GlButton, GlButton,
GlFormGroup, GlFormGroup,
GlFormCheckbox, GlFormCheckbox,
GlFormRadioGroup, GlFormRadioGroup,
GlFormRadio, GlFormRadio,
GlFormInputGroup, GlFormInputGroup,
GlLink,
GlSprintf,
} from '@gitlab/ui'; } from '@gitlab/ui';
import { mapActions, mapGetters, mapState } from 'vuex'; import { mapActions, mapGetters, mapState } from 'vuex';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { helpPagePath } from '~/helpers/help_page_helper';
import { I18N_ERROR_TRACKING_SETTINGS } from '../constants';
import ErrorTrackingForm from './error_tracking_form.vue'; import ErrorTrackingForm from './error_tracking_form.vue';
import ProjectDropdown from './project_dropdown.vue'; import ProjectDropdown from './project_dropdown.vue';
export default { export default {
i18n: I18N_ERROR_TRACKING_SETTINGS,
components: { components: {
ErrorTrackingForm, ErrorTrackingForm,
GlAlert,
GlButton, GlButton,
GlFormCheckbox, GlFormCheckbox,
GlFormGroup, GlFormGroup,
GlFormRadioGroup, GlFormRadioGroup,
GlFormRadio, GlFormRadio,
GlFormInputGroup, GlFormInputGroup,
GlLink,
GlSprintf,
ProjectDropdown, ProjectDropdown,
ClipboardButton, ClipboardButton,
}, },
mixins: [glFeatureFlagsMixin()],
props: { props: {
initialApiHost: { initialApiHost: {
type: String, type: String,
...@@ -62,6 +73,11 @@ export default { ...@@ -62,6 +73,11 @@ export default {
default: null, default: null,
}, },
}, },
data() {
return {
isAlertDismissed: false,
};
},
computed: { computed: {
...mapGetters([ ...mapGetters([
'dropdownLabel', 'dropdownLabel',
...@@ -81,12 +97,34 @@ export default { ...@@ -81,12 +97,34 @@ export default {
showGitlabDsnSetting() { showGitlabDsnSetting() {
return this.integrated && this.enabled && this.gitlabDsn; return this.integrated && this.enabled && this.gitlabDsn;
}, },
showIntegratedErrorTracking() {
return this.glFeatures.integratedErrorTracking === true;
},
setInitialEnabled() {
if (this.showIntegratedErrorTracking) {
return this.initialEnabled;
}
if (this.initialIntegrated === 'true') {
return 'false';
}
return this.initialEnabled;
},
showIntegratedTrackingDisabledAlert() {
return (
!this.isAlertDismissed &&
!this.showIntegratedErrorTracking &&
this.initialIntegrated === 'true' &&
this.initialEnabled === 'true'
);
}, },
},
epicLink: 'https://gitlab.com/gitlab-org/gitlab/-/issues/353639',
featureFlagLink: helpPagePath('operations/error_tracking'),
created() { created() {
this.setInitialState({ this.setInitialState({
apiHost: this.initialApiHost, apiHost: this.initialApiHost,
enabled: this.initialEnabled, enabled: this.setInitialEnabled,
integrated: this.initialIntegrated, integrated: this.showIntegratedErrorTracking && this.initialIntegrated,
project: this.initialProject, project: this.initialProject,
token: this.initialToken, token: this.initialToken,
listProjectsEndpoint: this.listProjectsEndpoint, listProjectsEndpoint: this.listProjectsEndpoint,
...@@ -104,21 +142,41 @@ export default { ...@@ -104,21 +142,41 @@ export default {
handleSubmit() { handleSubmit() {
this.updateSettings(); this.updateSettings();
}, },
dismissAlert() {
this.isAlertDismissed = true;
},
}, },
}; };
</script> </script>
<template> <template>
<div> <div>
<gl-alert v-if="showIntegratedTrackingDisabledAlert" variant="danger" @dismiss="dismissAlert">
<gl-sprintf :message="this.$options.i18n.integratedErrorTrackingDisabledText">
<template #epicLink="{ content }">
<gl-link :href="$options.epicLink" target="_blank">{{ content }}</gl-link>
</template>
<template #flagLink="{ content }">
<gl-link :href="$options.featureFlagLink" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
</gl-alert>
<gl-form-group <gl-form-group
:label="s__('ErrorTracking|Enable error tracking')" :label="s__('ErrorTracking|Enable error tracking')"
label-for="error-tracking-enabled" label-for="error-tracking-enabled"
> >
<gl-form-checkbox id="error-tracking-enabled" :checked="enabled" @change="updateEnabled"> <gl-form-checkbox
id="error-tracking-enabled"
:checked="enabled"
data-testid="error-tracking-enabled"
@change="updateEnabled"
>
{{ s__('ErrorTracking|Active') }} {{ s__('ErrorTracking|Active') }}
</gl-form-checkbox> </gl-form-checkbox>
</gl-form-group> </gl-form-group>
<gl-form-group <gl-form-group
v-if="showIntegratedErrorTracking"
:label="s__('ErrorTracking|Error tracking backend')" :label="s__('ErrorTracking|Error tracking backend')"
data-testid="tracking-backend-settings" data-testid="tracking-backend-settings"
> >
......
import { s__ } from '~/locale';
export const I18N_ERROR_TRACKING_SETTINGS = {
integratedErrorTrackingDisabledText: s__(
'ErrorTracking|Integrated error tracking is %{epicLinkStart}turned off by default%{epicLinkEnd} and no longer active for this project. To re-enable error tracking on self-hosted instances, you can either %{flagLinkStart}turn on the feature flag%{flagLinkEnd} for integrated error tracking, or provide a Sentry API URL and Auth Token below. However, error tracking is not ready for production use and cannot be enabled on GitLab.com.',
),
};
...@@ -6,6 +6,10 @@ class Projects::ErrorTrackingController < Projects::ErrorTracking::BaseControlle ...@@ -6,6 +6,10 @@ class Projects::ErrorTrackingController < Projects::ErrorTracking::BaseControlle
before_action :authorize_read_sentry_issue! before_action :authorize_read_sentry_issue!
before_action :set_issue_id, only: :details before_action :set_issue_id, only: :details
before_action only: [:index] do
push_frontend_feature_flag(:integrated_error_tracking, project)
end
def index def index
respond_to do |format| respond_to do |format|
format.html format.html
......
...@@ -7,6 +7,10 @@ module Projects ...@@ -7,6 +7,10 @@ module Projects
before_action :authorize_admin_operations! before_action :authorize_admin_operations!
before_action :authorize_read_prometheus_alerts!, only: [:reset_alerting_token] before_action :authorize_read_prometheus_alerts!, only: [:reset_alerting_token]
before_action do
push_frontend_feature_flag(:integrated_error_tracking, project)
end
respond_to :json, only: [:reset_alerting_token, :reset_pagerduty_token] respond_to :json, only: [:reset_alerting_token, :reset_pagerduty_token]
helper_method :error_tracking_setting helper_method :error_tracking_setting
......
...@@ -12,7 +12,8 @@ module Projects::ErrorTrackingHelper ...@@ -12,7 +12,8 @@ module Projects::ErrorTrackingHelper
'error-tracking-enabled' => error_tracking_enabled.to_s, 'error-tracking-enabled' => error_tracking_enabled.to_s,
'project-path' => project.full_path, 'project-path' => project.full_path,
'list-path' => project_error_tracking_index_path(project), 'list-path' => project_error_tracking_index_path(project),
'illustration-path' => image_path('illustrations/cluster_popover.svg') 'illustration-path' => image_path('illustrations/cluster_popover.svg'),
'show-integrated-tracking-disabled-alert' => show_integrated_tracking_disabled_alert?(project).to_s
} }
end end
...@@ -27,4 +28,15 @@ module Projects::ErrorTrackingHelper ...@@ -27,4 +28,15 @@ module Projects::ErrorTrackingHelper
'issue-stack-trace-path' => stack_trace_project_error_tracking_index_path(*opts) 'issue-stack-trace-path' => stack_trace_project_error_tracking_index_path(*opts)
} }
end end
private
def show_integrated_tracking_disabled_alert?(project)
return false if ::Feature.enabled?(:integrated_error_tracking, project)
setting ||= project.error_tracking_setting ||
project.build_error_tracking_setting
setting.integrated_enabled?
end
end end
...@@ -59,6 +59,10 @@ module ErrorTracking ...@@ -59,6 +59,10 @@ module ErrorTracking
integrated integrated
end end
def integrated_enabled?
enabled? && integrated_client?
end
def gitlab_dsn def gitlab_dsn
strong_memoize(:gitlab_dsn) do strong_memoize(:gitlab_dsn) do
client_key&.sentry_dsn client_key&.sentry_dsn
......
---
name: integrated_error_tracking
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81767
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/353956
milestone: '14.9'
type: development
group: group::respond
default_enabled: false
...@@ -129,7 +129,17 @@ If another event occurs, the error reverts to unresolved. ...@@ -129,7 +129,17 @@ If another event occurs, the error reverts to unresolved.
## Integrated error tracking ## Integrated error tracking
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/329596) in GitLab 14.4. > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/329596) in GitLab 14.4.
> - [Disabled](https://gitlab.com/gitlab-org/gitlab/-/issues/353639) in GitLab 14.9 [with a flag](../administration/feature_flags.md) named `integrated_error_tracking`. Disabled by default.
FLAG:
By default this feature is not available. To make it available on self-managed GitLab, ask an
administrator to [enable the feature flag](../administration/feature_flags.md)
named `integrated_error_tracking`. The feature is not ready for production use.
On GitLab.com, this feature is not available.
WARNING:
Turning on integrated error tracking may impact performance, depending on your error rates.
Integrated error tracking is a lightweight alternative to Sentry backend. Integrated error tracking is a lightweight alternative to Sentry backend.
You still use Sentry SDK with your application. But you don't need to deploy Sentry You still use Sentry SDK with your application. But you don't need to deploy Sentry
......
...@@ -9,6 +9,12 @@ module API ...@@ -9,6 +9,12 @@ module API
expose :sentry_external_url expose :sentry_external_url
expose :api_url expose :api_url
expose :integrated expose :integrated
def integrated
return false unless ::Feature.enabled?(:integrated_error_tracking, object.project)
object.integrated_client?
end
end end
class ClientKey < Grape::Entity class ClientKey < Grape::Entity
......
...@@ -28,8 +28,8 @@ module API ...@@ -28,8 +28,8 @@ module API
end end
def feature_enabled? def feature_enabled?
project.error_tracking_setting&.enabled? && Feature.enabled?(:integrated_error_tracking, project) &&
project.error_tracking_setting&.integrated_client? project.error_tracking_setting&.integrated_enabled?
end end
def find_client_key(public_key) def find_client_key(public_key)
......
...@@ -14443,6 +14443,12 @@ msgstr "" ...@@ -14443,6 +14443,12 @@ msgstr ""
msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io" msgid "ErrorTracking|If you self-host Sentry, enter your Sentry instance's full URL. If you use Sentry's hosted solution, enter https://sentry.io"
msgstr "" msgstr ""
msgid "ErrorTracking|Integrated error tracking is %{epicLinkStart}turned off by default%{epicLinkEnd} and no longer active for this project. To re-enable error tracking on self-hosted instances, you can either %{flagLinkStart}turn on the feature flag%{flagLinkEnd} for integrated error tracking, or provide a %{settingsLinkStart}Sentry API URL and Auth Token%{settingsLinkEnd} on your project settings page. However, error tracking is not ready for production use and cannot be enabled on GitLab.com."
msgstr ""
msgid "ErrorTracking|Integrated error tracking is %{epicLinkStart}turned off by default%{epicLinkEnd} and no longer active for this project. To re-enable error tracking on self-hosted instances, you can either %{flagLinkStart}turn on the feature flag%{flagLinkEnd} for integrated error tracking, or provide a Sentry API URL and Auth Token below. However, error tracking is not ready for production use and cannot be enabled on GitLab.com."
msgstr ""
msgid "ErrorTracking|No projects available" msgid "ErrorTracking|No projects available"
msgstr "" msgstr ""
...@@ -14452,6 +14458,9 @@ msgstr "" ...@@ -14452,6 +14458,9 @@ msgstr ""
msgid "ErrorTracking|To enable project selection, enter a valid Auth Token." msgid "ErrorTracking|To enable project selection, enter a valid Auth Token."
msgstr "" msgstr ""
msgid "ErrorTracking|View project settings"
msgstr ""
msgid "Errors" msgid "Errors"
msgstr "" msgstr ""
......
...@@ -10,11 +10,7 @@ import { ...@@ -10,11 +10,7 @@ import {
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue'; import Vue, { nextTick } from 'vue';
import Vuex from 'vuex'; import Vuex from 'vuex';
import { import { severityLevel, severityLevelVariant, errorStatus } from '~/error_tracking/constants';
severityLevel,
severityLevelVariant,
errorStatus,
} from '~/error_tracking/components/constants';
import ErrorDetails from '~/error_tracking/components/error_details.vue'; import ErrorDetails from '~/error_tracking/components/error_details.vue';
import Stacktrace from '~/error_tracking/components/stacktrace.vue'; import Stacktrace from '~/error_tracking/components/stacktrace.vue';
import { import {
......
...@@ -7,6 +7,7 @@ import ErrorTrackingActions from '~/error_tracking/components/error_tracking_act ...@@ -7,6 +7,7 @@ import ErrorTrackingActions from '~/error_tracking/components/error_tracking_act
import ErrorTrackingList from '~/error_tracking/components/error_tracking_list.vue'; import ErrorTrackingList from '~/error_tracking/components/error_tracking_list.vue';
import { trackErrorListViewsOptions, trackErrorStatusUpdateOptions } from '~/error_tracking/utils'; import { trackErrorListViewsOptions, trackErrorStatusUpdateOptions } from '~/error_tracking/utils';
import Tracking from '~/tracking'; import Tracking from '~/tracking';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import errorsList from './list_mock.json'; import errorsList from './list_mock.json';
Vue.use(Vuex); Vue.use(Vuex);
...@@ -25,13 +26,16 @@ describe('ErrorTrackingList', () => { ...@@ -25,13 +26,16 @@ describe('ErrorTrackingList', () => {
const findLoadingIcon = () => wrapper.find(GlLoadingIcon); const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
const findPagination = () => wrapper.find(GlPagination); const findPagination = () => wrapper.find(GlPagination);
const findErrorActions = () => wrapper.find(ErrorTrackingActions); const findErrorActions = () => wrapper.find(ErrorTrackingActions);
const findIntegratedDisabledAlert = () => wrapper.findByTestId('integrated-disabled-alert');
function mountComponent({ function mountComponent({
errorTrackingEnabled = true, errorTrackingEnabled = true,
userCanEnableErrorTracking = true, userCanEnableErrorTracking = true,
showIntegratedTrackingDisabledAlert = false,
stubs = {}, stubs = {},
} = {}) { } = {}) {
wrapper = mount(ErrorTrackingList, { wrapper = extendedWrapper(
mount(ErrorTrackingList, {
store, store,
propsData: { propsData: {
indexPath: '/path', indexPath: '/path',
...@@ -40,13 +44,15 @@ describe('ErrorTrackingList', () => { ...@@ -40,13 +44,15 @@ describe('ErrorTrackingList', () => {
enableErrorTrackingLink: '/link', enableErrorTrackingLink: '/link',
userCanEnableErrorTracking, userCanEnableErrorTracking,
errorTrackingEnabled, errorTrackingEnabled,
showIntegratedTrackingDisabledAlert,
illustrationPath: 'illustration/path', illustrationPath: 'illustration/path',
}, },
stubs: { stubs: {
...stubChildren(ErrorTrackingList), ...stubChildren(ErrorTrackingList),
...stubs, ...stubs,
}, },
}); }),
);
} }
beforeEach(() => { beforeEach(() => {
...@@ -223,6 +229,31 @@ describe('ErrorTrackingList', () => { ...@@ -223,6 +229,31 @@ describe('ErrorTrackingList', () => {
}); });
}); });
describe('When the integrated tracking diabled alert should be shown', () => {
beforeEach(() => {
mountComponent({
showIntegratedTrackingDisabledAlert: true,
stubs: {
GlAlert: false,
},
});
});
it('shows the alert box', () => {
expect(findIntegratedDisabledAlert().exists()).toBe(true);
});
describe('when alert is dismissed', () => {
it('hides the alert box', async () => {
findIntegratedDisabledAlert().vm.$emit('dismiss');
await nextTick();
expect(findIntegratedDisabledAlert().exists()).toBe(false);
});
});
});
describe('When the ignore button on an error is clicked', () => { describe('When the ignore button on an error is clicked', () => {
beforeEach(() => { beforeEach(() => {
store.state.list.loading = false; store.state.list.loading = false;
......
...@@ -18,11 +18,7 @@ describe('error tracking settings app', () => { ...@@ -18,11 +18,7 @@ describe('error tracking settings app', () => {
let store; let store;
let wrapper; let wrapper;
function mountComponent() { const defaultProps = {
wrapper = extendedWrapper(
shallowMount(ErrorTrackingSettings, {
store, // Override the imported store
propsData: {
initialEnabled: 'true', initialEnabled: 'true',
initialIntegrated: 'false', initialIntegrated: 'false',
initialApiHost: TEST_HOST, initialApiHost: TEST_HOST,
...@@ -31,6 +27,18 @@ describe('error tracking settings app', () => { ...@@ -31,6 +27,18 @@ describe('error tracking settings app', () => {
listProjectsEndpoint: TEST_HOST, listProjectsEndpoint: TEST_HOST,
operationsSettingsEndpoint: TEST_HOST, operationsSettingsEndpoint: TEST_HOST,
gitlabDsn: TEST_GITLAB_DSN, gitlabDsn: TEST_GITLAB_DSN,
};
function mountComponent({
glFeatures = { integratedErrorTracking: false },
props = defaultProps,
} = {}) {
wrapper = extendedWrapper(
shallowMount(ErrorTrackingSettings, {
store, // Override the imported store
propsData: { ...props },
provide: {
glFeatures,
}, },
stubs: { stubs: {
GlFormInputGroup, // we need this non-shallow to query for a component within a slot GlFormInputGroup, // we need this non-shallow to query for a component within a slot
...@@ -47,6 +55,7 @@ describe('error tracking settings app', () => { ...@@ -47,6 +55,7 @@ describe('error tracking settings app', () => {
const findElementWithText = (wrappers, text) => wrappers.filter((item) => item.text() === text); const findElementWithText = (wrappers, text) => wrappers.filter((item) => item.text() === text);
const findSentrySettings = () => wrapper.findByTestId('sentry-setting-form'); const findSentrySettings = () => wrapper.findByTestId('sentry-setting-form');
const findDsnSettings = () => wrapper.findByTestId('gitlab-dsn-setting-form'); const findDsnSettings = () => wrapper.findByTestId('gitlab-dsn-setting-form');
const findEnabledCheckbox = () => wrapper.findByTestId('error-tracking-enabled');
const enableGitLabErrorTracking = async () => { const enableGitLabErrorTracking = async () => {
findBackendSettingsRadioGroup().vm.$emit('change', true); findBackendSettingsRadioGroup().vm.$emit('change', true);
...@@ -88,6 +97,47 @@ describe('error tracking settings app', () => { ...@@ -88,6 +97,47 @@ describe('error tracking settings app', () => {
}); });
describe('tracking-backend settings', () => { describe('tracking-backend settings', () => {
it('does not contain backend settings section', () => {
expect(findBackendSettingsSection().exists()).toBe(false);
});
it('shows the sentry form', () => {
expect(findSentrySettings().exists()).toBe(true);
});
describe('enabled setting is true', () => {
describe('integrated setting is true', () => {
beforeEach(() => {
mountComponent({
props: { ...defaultProps, initialEnabled: 'true', initialIntegrated: 'true' },
});
});
it('displays enabled as false', () => {
expect(findEnabledCheckbox().attributes('checked')).toBeUndefined();
});
});
describe('integrated setting is false', () => {
beforeEach(() => {
mountComponent({
props: { ...defaultProps, initialEnabled: 'true', initialIntegrated: 'false' },
});
});
it('displays enabled as true', () => {
expect(findEnabledCheckbox().attributes('checked')).toBe('true');
});
});
});
describe('integrated_error_tracking feature flag enabled', () => {
beforeEach(() => {
mountComponent({
glFeatures: { integratedErrorTracking: true },
});
});
it('contains a form-group with the correct label', () => { it('contains a form-group with the correct label', () => {
expect(findBackendSettingsSection().attributes('label')).toBe('Error tracking backend'); expect(findBackendSettingsSection().attributes('label')).toBe('Error tracking backend');
}); });
...@@ -146,4 +196,5 @@ describe('error tracking settings app', () => { ...@@ -146,4 +196,5 @@ describe('error tracking settings app', () => {
}, },
); );
}); });
});
}); });
...@@ -34,7 +34,8 @@ RSpec.describe Projects::ErrorTrackingHelper do ...@@ -34,7 +34,8 @@ RSpec.describe Projects::ErrorTrackingHelper do
'error-tracking-enabled' => 'false', 'error-tracking-enabled' => 'false',
'list-path' => list_path, 'list-path' => list_path,
'project-path' => project_path, 'project-path' => project_path,
'illustration-path' => match_asset_path('/assets/illustrations/cluster_popover.svg') 'illustration-path' => match_asset_path('/assets/illustrations/cluster_popover.svg'),
'show-integrated-tracking-disabled-alert' => 'false'
) )
end end
end end
...@@ -67,6 +68,37 @@ RSpec.describe Projects::ErrorTrackingHelper do ...@@ -67,6 +68,37 @@ RSpec.describe Projects::ErrorTrackingHelper do
) )
end end
end end
context 'with integrated error tracking feature' do
using RSpec::Parameterized::TableSyntax
where(:feature_flag, :enabled, :integrated, :show_alert) do
false | true | true | true
false | true | false | false
false | false | true | false
false | false | false | false
true | true | true | false
true | true | false | false
true | false | true | false
true | false | false | false
end
with_them do
before do
stub_feature_flags(integrated_error_tracking: feature_flag)
error_tracking_setting.update_columns(
enabled: enabled,
integrated: integrated
)
end
specify do
expect(helper.error_tracking_data(current_user, project)).to include(
'show-integrated-tracking-disabled-alert' => show_alert.to_s
)
end
end
end
end end
context 'when user is not maintainer' do context 'when user is not maintainer' do
......
...@@ -535,6 +535,25 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do ...@@ -535,6 +535,25 @@ RSpec.describe ErrorTracking::ProjectErrorTrackingSetting do
end end
end end
describe '#integrated_enabled?' do
using RSpec::Parameterized::TableSyntax
where(:enabled, :integrated, :integrated_enabled) do
true | false | false
false | true | false
true | true | true
end
with_them do
before do
subject.enabled = enabled
subject.integrated = integrated
end
it { expect(subject.integrated_enabled?).to eq(integrated_enabled) }
end
end
describe '#gitlab_dsn' do describe '#gitlab_dsn' do
let!(:client_key) { create(:error_tracking_client_key, project: project) } let!(:client_key) { create(:error_tracking_client_key, project: project) }
......
...@@ -26,7 +26,6 @@ RSpec.describe API::ErrorTracking::Collector do ...@@ -26,7 +26,6 @@ RSpec.describe API::ErrorTracking::Collector do
RSpec.shared_examples 'successful request' do RSpec.shared_examples 'successful request' do
it 'writes to the database and returns OK', :aggregate_failures do it 'writes to the database and returns OK', :aggregate_failures do
expect { subject }.to change { ErrorTracking::ErrorEvent.count }.by(1) expect { subject }.to change { ErrorTracking::ErrorEvent.count }.by(1)
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
end end
end end
...@@ -42,6 +41,14 @@ RSpec.describe API::ErrorTracking::Collector do ...@@ -42,6 +41,14 @@ RSpec.describe API::ErrorTracking::Collector do
it_behaves_like 'successful request' it_behaves_like 'successful request'
context 'intergrated error tracking feature flag is disabled' do
before do
stub_feature_flags(integrated_error_tracking: false)
end
it_behaves_like 'not found'
end
context 'error tracking feature is disabled' do context 'error tracking feature is disabled' do
before do before do
setting.update!(enabled: false) setting.update!(enabled: false)
......
...@@ -23,6 +23,21 @@ RSpec.describe API::ErrorTracking::ProjectSettings do ...@@ -23,6 +23,21 @@ RSpec.describe API::ErrorTracking::ProjectSettings do
end end
end end
shared_examples 'returns project settings with false for integrated' do
specify do
make_request
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to eq(
'active' => setting.reload.enabled,
'project_name' => setting.project_name,
'sentry_external_url' => setting.sentry_external_url,
'api_url' => setting.api_url,
'integrated' => false
)
end
end
shared_examples 'returns 404' do shared_examples 'returns 404' do
it 'returns no project settings' do it 'returns no project settings' do
make_request make_request
...@@ -46,7 +61,17 @@ RSpec.describe API::ErrorTracking::ProjectSettings do ...@@ -46,7 +61,17 @@ RSpec.describe API::ErrorTracking::ProjectSettings do
end end
context 'patch settings' do context 'patch settings' do
context 'integrated_error_tracking feature enabled' do
it_behaves_like 'returns project settings' it_behaves_like 'returns project settings'
end
context 'integrated_error_tracking feature disabled' do
before do
stub_feature_flags(integrated_error_tracking: false)
end
it_behaves_like 'returns project settings with false for integrated'
end
it 'updates enabled flag' do it 'updates enabled flag' do
expect(setting).to be_enabled expect(setting).to be_enabled
...@@ -84,6 +109,11 @@ RSpec.describe API::ErrorTracking::ProjectSettings do ...@@ -84,6 +109,11 @@ RSpec.describe API::ErrorTracking::ProjectSettings do
context 'with integrated param' do context 'with integrated param' do
let(:params) { { active: true, integrated: true } } let(:params) { { active: true, integrated: true } }
context 'integrated_error_tracking feature enabled' do
before do
stub_feature_flags(integrated_error_tracking: true)
end
it 'updates the integrated flag' do it 'updates the integrated flag' do
expect(setting.integrated).to be_falsey expect(setting.integrated).to be_falsey
...@@ -94,6 +124,7 @@ RSpec.describe API::ErrorTracking::ProjectSettings do ...@@ -94,6 +124,7 @@ RSpec.describe API::ErrorTracking::ProjectSettings do
end end
end end
end end
end
context 'without a project setting' do context 'without a project setting' do
let(:project) { create(:project) } let(:project) { create(:project) }
...@@ -170,8 +201,22 @@ RSpec.describe API::ErrorTracking::ProjectSettings do ...@@ -170,8 +201,22 @@ RSpec.describe API::ErrorTracking::ProjectSettings do
end end
context 'get settings' do context 'get settings' do
context 'integrated_error_tracking feature enabled' do
before do
stub_feature_flags(integrated_error_tracking: true)
end
it_behaves_like 'returns project settings' it_behaves_like 'returns project settings'
end end
context 'integrated_error_tracking feature disabled' do
before do
stub_feature_flags(integrated_error_tracking: false)
end
it_behaves_like 'returns project settings with false for integrated'
end
end
end end
context 'without a project setting' do context 'without a project setting' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment