diff --git a/ee/app/assets/javascripts/compliance_dashboard/components/standards_adherence_report/base_table.vue b/ee/app/assets/javascripts/compliance_dashboard/components/standards_adherence_report/base_table.vue index 54f853aac6f787e3c27ca0d2411475ccdee41857..1442bf4df61324f688cdcdf2870fa1439fd831c2 100644 --- a/ee/app/assets/javascripts/compliance_dashboard/components/standards_adherence_report/base_table.vue +++ b/ee/app/assets/javascripts/compliance_dashboard/components/standards_adherence_report/base_table.vue @@ -7,8 +7,8 @@ import getProjectComplianceStandardsGroupAdherence from 'ee/compliance_dashboard import getProjectComplianceStandardsProjectAdherence from 'ee/compliance_dashboard/graphql/compliance_standards_project_adherence.query.graphql'; import FrameworksInfo from '../shared/frameworks_info.vue'; import Pagination from '../shared/pagination.vue'; -import { GRAPHQL_PAGE_SIZE } from '../../constants'; -import { isTopLevelGroup } from '../../utils'; +import { GRAPHQL_PAGE_SIZE, GRAPHQL_FIELD_MISSING_ERROR_MESSAGE } from '../../constants'; +import { isTopLevelGroup, isGraphqlFieldMissingError } from '../../utils'; import { FAIL_STATUS, STANDARDS_ADHERENCE_CHECK_LABELS, @@ -61,6 +61,7 @@ export default { data() { return { hasStandardsAdherenceFetchError: false, + customErrorText: null, hasFilterValueError: false, drawerId: null, drawerAdherence: {}, @@ -94,6 +95,9 @@ export default { error(e) { Sentry.captureException(e); this.hasStandardsAdherenceFetchError = true; + this.customErrorText = isGraphqlFieldMissingError(e, 'projectComplianceStandardsAdherence') + ? GRAPHQL_FIELD_MISSING_ERROR_MESSAGE + : null; }, }, }, @@ -269,7 +273,7 @@ export default { class="gl-mt-3" :dismissible="false" > - {{ $options.standardsAdherenceFetchError }} + {{ customErrorText || $options.standardsAdherenceFetchError }} </gl-alert> <gl-table :fields="fields" diff --git a/ee/app/assets/javascripts/compliance_dashboard/components/violations_report/report.vue b/ee/app/assets/javascripts/compliance_dashboard/components/violations_report/report.vue index 93e87dac6213ce99503e72d047c19e25601845f2..5ff5ef61d21655f68e9eeea194053ee05d899a78 100644 --- a/ee/app/assets/javascripts/compliance_dashboard/components/violations_report/report.vue +++ b/ee/app/assets/javascripts/compliance_dashboard/components/violations_report/report.vue @@ -11,11 +11,17 @@ import { ISO_SHORT_FORMAT } from '~/vue_shared/constants'; import getComplianceViolationsGroupQuery from '../../graphql/compliance_violations_group.query.graphql'; import getComplianceViolationsProjectQuery from '../../graphql/compliance_violations_project.query.graphql'; import { mapViolations } from '../../graphql/mappers'; -import { DEFAULT_PAGINATION_CURSORS, DEFAULT_SORT, GRAPHQL_PAGE_SIZE } from '../../constants'; +import { + DEFAULT_PAGINATION_CURSORS, + DEFAULT_SORT, + GRAPHQL_PAGE_SIZE, + GRAPHQL_FIELD_MISSING_ERROR_MESSAGE, +} from '../../constants'; import { buildDefaultViolationsFilterParams, isTopLevelGroup, parseViolationsQueryFilter, + isGraphqlFieldMissingError, } from '../../utils'; import MergeRequestDrawer from './drawer.vue'; import ViolationReason from './violations/reason.vue'; @@ -63,6 +69,7 @@ export default { defaultFilterParams, urlQuery: { ...defaultFilterParams }, queryError: false, + customErrorText: false, violations: { list: [], pageInfo: {}, @@ -109,6 +116,9 @@ export default { error(e) { Sentry.captureException(e); this.queryError = true; + this.customErrorText = isGraphqlFieldMissingError(e, 'mergeRequestViolations') + ? GRAPHQL_FIELD_MISSING_ERROR_MESSAGE + : null; }, }, }, @@ -247,7 +257,7 @@ export default { <template> <section> <gl-alert v-if="queryError" variant="danger" class="gl-mt-3" :dismissible="false"> - {{ $options.i18n.queryError }} + {{ customErrorText || $options.i18n.queryError }} </gl-alert> <violation-filter :show-project-filter="!projectPath" diff --git a/ee/app/assets/javascripts/compliance_dashboard/constants.js b/ee/app/assets/javascripts/compliance_dashboard/constants.js index 52350ca672216f0fb2d9ed67c42e2a1079ec6f45..f082865990618d69eb3eebcad52fdfa94d008a7c 100644 --- a/ee/app/assets/javascripts/compliance_dashboard/constants.js +++ b/ee/app/assets/javascripts/compliance_dashboard/constants.js @@ -77,3 +77,7 @@ export const POLICY_SCOPES_DOCS_URL = `${DOCS_URL_IN_EE_DIR}/user/application_se export const CREATE_FRAMEWORKS_DOCS_URL = `${DOCS_URL_IN_EE_DIR}/user/group/compliance_frameworks.html#prerequisites`; export const FEEDBACK_ISSUE_URL = 'https://gitlab.com/gitlab-org/gitlab/-/issues/481586'; + +export const GRAPHQL_FIELD_MISSING_ERROR_MESSAGE = __( + 'Your GitLab instance is currently being updated. Please try again later.', +); diff --git a/ee/app/assets/javascripts/compliance_dashboard/utils.js b/ee/app/assets/javascripts/compliance_dashboard/utils.js index 7c208b37497703139b5798ef7295dbe102c3a1b0..5eb3b2571a20317bf0baf8412eb9a6b7359ace77 100644 --- a/ee/app/assets/javascripts/compliance_dashboard/utils.js +++ b/ee/app/assets/javascripts/compliance_dashboard/utils.js @@ -126,3 +126,11 @@ export function mapStandardsAdherenceQueryToFilters(filters) { return filterParams; } + +export const isGraphqlFieldMissingError = (error, field) => { + return Boolean( + error?.graphQLErrors?.some((e) => + e?.message?.startsWith(`Field '${field}' doesn't exist on type`), + ), + ); +}; diff --git a/ee/spec/frontend/compliance_dashboard/utils_spec.js b/ee/spec/frontend/compliance_dashboard/utils_spec.js index 2e24bd76bf15301a69eb6d3197f38c3cfe0d5524..7239a076096b334aebbec7ab8c3dfa3517e78a3f 100644 --- a/ee/spec/frontend/compliance_dashboard/utils_spec.js +++ b/ee/spec/frontend/compliance_dashboard/utils_spec.js @@ -1,4 +1,5 @@ import timezoneMock from 'timezone-mock'; +import { ApolloError } from '@apollo/client/core'; import * as utils from 'ee/compliance_dashboard/utils'; import { FRAMEWORKS_FILTER_TYPE_FRAMEWORK, @@ -241,4 +242,25 @@ describe('compliance report utils', () => { expect(utils.checkFilterForChange({ currentFilters, newFilters })).toBe(false); }); }); + + describe('isGraphqlFieldMissingError', () => { + const graphqlError = new ApolloError({ + graphQLErrors: [ + { + message: "Field 'foo' doesn't exist on type 'Project'", + }, + ], + }); + + it('returns true when error looks like graphql one and references correct field', () => { + expect(utils.isGraphqlFieldMissingError(graphqlError, 'foo')).toBe(true); + }); + + it('returns false when error looks like graphql one but references other field', () => { + expect(utils.isGraphqlFieldMissingError(graphqlError, 'bar')).toBe(false); + }); + it('returns false for other errors', () => { + expect(utils.isGraphqlFieldMissingError(new Error('test'), 'foo')).toBe(false); + }); + }); }); diff --git a/locale/gitlab.pot b/locale/gitlab.pot index e00417bfdfc70923583ff40a794ea7916815eea5..bf6021136257d7000831da1195008f06589b304a 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -63757,6 +63757,9 @@ msgstr "" msgid "Your GitLab instance allows anyone to register for an account, which is a security risk on public-facing GitLab instances. You should deactivate new sign ups if public users aren't expected to register for an account." msgstr "" +msgid "Your GitLab instance is currently being updated. Please try again later." +msgstr "" + msgid "Your GitLab version" msgstr ""