diff options
| author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-04-27 06:13:06 +0000 |
|---|---|---|
| committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-04-27 06:13:06 +0000 |
| commit | 3fbe43541ef99c27a9e4ab9c545ec0eb9bb50a9e (patch) | |
| tree | df71ce391f93b65a4f44fa719c8def2b9e45d40f | |
| parent | 0e1350d51ca2135e37743dfb7af98eae43c72892 (diff) | |
| download | gitlab-ce-3fbe43541ef99c27a9e4ab9c545ec0eb9bb50a9e.tar.gz | |
Add latest changes from gitlab-org/gitlab@master
56 files changed, 161 insertions, 918 deletions
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 0f4b55a20b9..14a5c3966b9 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -3ce8f3a93ef7a00dfe5d65d92aa917a24e74e499 +20bc01b4d81c0e101a3a6639a926a6b9d0d7d9ba diff --git a/app/assets/javascripts/issuable/components/related_issuable_item.vue b/app/assets/javascripts/issuable/components/related_issuable_item.vue index 63386d2e33d..e76b4c133a9 100644 --- a/app/assets/javascripts/issuable/components/related_issuable_item.vue +++ b/app/assets/javascripts/issuable/components/related_issuable_item.vue @@ -124,7 +124,7 @@ export default { 'issuable-info-container': !canReorder, 'card-body': canReorder, }" - class="item-body gl-display-flex gl-align-items-center gl-gap-3 gl-mx-n2" + class="item-body gl-display-flex gl-align-items-center gl-gap-3" > <div class="item-contents gl-display-flex gl-align-items-center gl-flex-wrap gl-flex-grow-1 gl-gap-2 gl-px-3 gl-py-2 py-xl-0 flex-xl-nowrap gl-min-h-7" diff --git a/app/assets/javascripts/issues/related_merge_requests/components/related_merge_requests.vue b/app/assets/javascripts/issues/related_merge_requests/components/related_merge_requests.vue index c3f87699d58..8490ffd33cd 100644 --- a/app/assets/javascripts/issues/related_merge_requests/components/related_merge_requests.vue +++ b/app/assets/javascripts/issues/related_merge_requests/components/related_merge_requests.vue @@ -116,6 +116,7 @@ export default { :is-merge-request="true" :pipeline-status="mr.head_pipeline && mr.head_pipeline.detailed_status" path-id-separator="!" + class="gl-mx-n2" /> </li> </ul> diff --git a/app/assets/javascripts/jira_connect/subscriptions/api.js b/app/assets/javascripts/jira_connect/subscriptions/api.js index 8c5dc88f183..184635e63f3 100644 --- a/app/assets/javascripts/jira_connect/subscriptions/api.js +++ b/app/assets/javascripts/jira_connect/subscriptions/api.js @@ -16,15 +16,6 @@ export const setApiBaseURL = (baseURL = null) => { axiosInstance.defaults.baseURL = baseURL; }; -export const addSubscription = async (addPath, namespace) => { - const jwt = await getJwt(); - - return axiosInstance.post(addPath, { - jwt, - namespace_path: namespace, - }); -}; - export const removeSubscription = async (removePath) => { const jwt = await getJwt(); diff --git a/app/assets/javascripts/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item.vue b/app/assets/javascripts/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item.vue index d918559a49f..cd0f4c2f66f 100644 --- a/app/assets/javascripts/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item.vue +++ b/app/assets/javascripts/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item.vue @@ -1,27 +1,15 @@ <script> import { mapActions } from 'vuex'; import { GlButton } from '@gitlab/ui'; -import { addSubscription } from '~/jira_connect/subscriptions/api'; -import { persistAlert, reloadPage } from '~/jira_connect/subscriptions/utils'; -import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import GroupItemName from '../group_item_name.vue'; -import { - INTEGRATIONS_DOC_LINK, - I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_TITLE, - I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_MESSAGE, - I18N_ADD_SUBSCRIPTIONS_ERROR_MESSAGE, -} from '../../constants'; +import { I18N_ADD_SUBSCRIPTIONS_ERROR_MESSAGE } from '../../constants'; export default { components: { GlButton, GroupItemName, }, - mixins: [glFeatureFlagMixin()], inject: { - addSubscriptionsPath: { - default: '', - }, subscriptionsPath: { default: '', }, @@ -46,30 +34,15 @@ export default { ...mapActions(['addSubscription']), async onClick() { this.isLoading = true; - await this.addSubscription({ - namespacePath: this.group.full_path, - subscriptionsPath: this.subscriptionsPath, - }); - this.isLoading = false; - }, - deprecatedAddSubscription() { - this.isLoading = true; - - addSubscription(this.addSubscriptionsPath, this.group.full_path) - .then(() => { - persistAlert({ - title: I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_TITLE, - message: I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_MESSAGE, - linkUrl: INTEGRATIONS_DOC_LINK, - variant: 'success', - }); - - reloadPage(); - }) - .catch((error) => { - this.$emit('error', error?.response?.data?.error || I18N_ADD_SUBSCRIPTIONS_ERROR_MESSAGE); - this.isLoading = false; + try { + await this.addSubscription({ + namespacePath: this.group.full_path, + subscriptionsPath: this.subscriptionsPath, }); + } catch (error) { + this.$emit('error', error?.response?.data?.error || I18N_ADD_SUBSCRIPTIONS_ERROR_MESSAGE); + } + this.isLoading = false; }, }, }; diff --git a/app/assets/javascripts/jira_connect/subscriptions/components/app.vue b/app/assets/javascripts/jira_connect/subscriptions/components/app.vue index 1dc3f76b253..15e61ff1cd9 100644 --- a/app/assets/javascripts/jira_connect/subscriptions/components/app.vue +++ b/app/assets/javascripts/jira_connect/subscriptions/components/app.vue @@ -4,7 +4,6 @@ import { isEmpty } from 'lodash'; import { mapState, mapMutations, mapActions } from 'vuex'; import { retrieveAlert } from '~/jira_connect/subscriptions/utils'; import AccessorUtilities from '~/lib/utils/accessor'; -import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { I18N_DEFAULT_SIGN_IN_ERROR_MESSAGE } from '../constants'; import { SET_ALERT } from '../store/mutation_types'; import SignInPage from '../pages/sign_in/sign_in_page.vue'; @@ -23,11 +22,7 @@ export default { SubscriptionsPage, UserLink, }, - mixins: [glFeatureFlagMixin()], inject: { - usersPath: { - default: '', - }, subscriptionsPath: { default: '', }, diff --git a/app/assets/javascripts/jira_connect/subscriptions/components/sign_in_legacy_button.vue b/app/assets/javascripts/jira_connect/subscriptions/components/sign_in_legacy_button.vue deleted file mode 100644 index ec718d5b3ca..00000000000 --- a/app/assets/javascripts/jira_connect/subscriptions/components/sign_in_legacy_button.vue +++ /dev/null @@ -1,40 +0,0 @@ -<script> -import { GlButton } from '@gitlab/ui'; -import { getGitlabSignInURL } from '~/jira_connect/subscriptions/utils'; -import { I18N_DEFAULT_SIGN_IN_BUTTON_TEXT } from '~/jira_connect/subscriptions/constants'; - -export default { - components: { - GlButton, - }, - props: { - usersPath: { - type: String, - required: true, - }, - }, - data() { - return { - signInURL: '', - }; - }, - created() { - this.setSignInURL(); - }, - methods: { - async setSignInURL() { - this.signInURL = await getGitlabSignInURL(this.usersPath); - }, - }, - i18n: { - defaultButtonText: I18N_DEFAULT_SIGN_IN_BUTTON_TEXT, - }, -}; -</script> -<template> - <gl-button category="primary" variant="info" :href="signInURL" target="_blank"> - <slot> - {{ $options.i18n.defaultButtonText }} - </slot> - </gl-button> -</template> diff --git a/app/assets/javascripts/jira_connect/subscriptions/components/sign_in_oauth_button.vue b/app/assets/javascripts/jira_connect/subscriptions/components/sign_in_oauth_button.vue index 65c69bcfa82..bc8cdf35701 100644 --- a/app/assets/javascripts/jira_connect/subscriptions/components/sign_in_oauth_button.vue +++ b/app/assets/javascripts/jira_connect/subscriptions/components/sign_in_oauth_button.vue @@ -12,6 +12,7 @@ import { I18N_OAUTH_FAILED_MESSAGE, OAUTH_SELF_MANAGED_DOC_LINK, OAUTH_WINDOW_OPTIONS, + OAUTH_CALLBACK_MESSAGE_TYPE, PKCE_CODE_CHALLENGE_DIGEST_ALGORITHM, } from '~/jira_connect/subscriptions/constants'; import { fetchOAuthApplicationId, fetchOAuthToken } from '~/jira_connect/subscriptions/api'; @@ -130,6 +131,11 @@ export default { } }, async handleWindowMessage(event) { + // Make sure this ia a message from the OAuth flow in pages/jira_connect/oauth_callbacks/index.js + if (event.data?.type !== OAUTH_CALLBACK_MESSAGE_TYPE) { + return; + } + if (window.origin !== event.origin) { this.loading = false; return; diff --git a/app/assets/javascripts/jira_connect/subscriptions/components/user_link.vue b/app/assets/javascripts/jira_connect/subscriptions/components/user_link.vue index 9e1203f21d2..d05e0d8610e 100644 --- a/app/assets/javascripts/jira_connect/subscriptions/components/user_link.vue +++ b/app/assets/javascripts/jira_connect/subscriptions/components/user_link.vue @@ -1,8 +1,6 @@ <script> import { GlLink, GlSprintf } from '@gitlab/ui'; -import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { __ } from '~/locale'; -import { getGitlabSignInURL } from '~/jira_connect/subscriptions/utils'; export default { components: { @@ -10,11 +8,7 @@ export default { GlSprintf, SignInOauthButton: () => import('./sign_in_oauth_button.vue'), }, - mixins: [glFeatureFlagMixin()], inject: { - usersPath: { - default: '', - }, gitlabUserPath: { default: '', }, @@ -34,11 +28,6 @@ export default { default: null, }, }, - data() { - return { - signInURL: '', - }; - }, computed: { gitlabUserName() { return gon.current_username ?? this.user?.username; @@ -55,9 +44,6 @@ export default { : this.$options.i18n.signedInText; }, }, - async created() { - this.signInURL = await getGitlabSignInURL(this.usersPath); - }, i18n: { signInText: __('Sign in to GitLab'), signedInAsUserText: __('Signed in to GitLab as %{user_link}'), diff --git a/app/assets/javascripts/jira_connect/subscriptions/constants.js b/app/assets/javascripts/jira_connect/subscriptions/constants.js index bb22a4ef252..321d10205e6 100644 --- a/app/assets/javascripts/jira_connect/subscriptions/constants.js +++ b/app/assets/javascripts/jira_connect/subscriptions/constants.js @@ -54,6 +54,8 @@ export const OAUTH_WINDOW_OPTIONS = [ `top=${window.screen.height / 2 - OAUTH_WINDOW_SIZE / 2}`, ].join(','); +export const OAUTH_CALLBACK_MESSAGE_TYPE = 'jiraConnectOauthCallback'; + export const PKCE_CODE_CHALLENGE_DIGEST_ALGORITHM = { long: 'SHA-256', short: 'S256', diff --git a/app/assets/javascripts/jira_connect/subscriptions/index.js b/app/assets/javascripts/jira_connect/subscriptions/index.js index 21ff85e58e2..8854157054d 100644 --- a/app/assets/javascripts/jira_connect/subscriptions/index.js +++ b/app/assets/javascripts/jira_connect/subscriptions/index.js @@ -2,7 +2,6 @@ import '~/webpack'; import setConfigs from '@gitlab/ui/dist/config'; import Vue from 'vue'; -import GlFeatureFlagsPlugin from '~/vue_shared/gl_feature_flags_plugin'; import Translate from '~/vue_shared/translate'; import JiraConnectApp from './components/app.vue'; @@ -17,14 +16,11 @@ export function initJiraConnect() { setConfigs(); Vue.use(Translate); - Vue.use(GlFeatureFlagsPlugin); const { groupsPath, subscriptions, - addSubscriptionsPath, subscriptionsPath, - usersPath, gitlabUserPath, oauthMetadata, publicKeyStorageEnabled, @@ -38,9 +34,7 @@ export function initJiraConnect() { store, provide: { groupsPath, - addSubscriptionsPath, subscriptionsPath, - usersPath, gitlabUserPath, oauthMetadata: oauthMetadata ? JSON.parse(oauthMetadata) : null, publicKeyStorageEnabled, diff --git a/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_com.vue b/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_com.vue index 8a3a1768d5e..113ce34fdcd 100644 --- a/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_com.vue +++ b/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_com.vue @@ -2,7 +2,6 @@ import { s__ } from '~/locale'; import { GITLAB_COM_BASE_PATH } from '~/jira_connect/subscriptions/constants'; -import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import SubscriptionsList from '../../components/subscriptions_list.vue'; export default { @@ -11,8 +10,6 @@ export default { SubscriptionsList, SignInOauthButton: () => import('../../components/sign_in_oauth_button.vue'), }, - mixins: [glFeatureFlagMixin()], - inject: ['usersPath'], props: { hasSubscriptions: { type: Boolean, diff --git a/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_page.vue b/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_page.vue index 97ac88a03e9..ee20e21011f 100644 --- a/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_page.vue +++ b/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_page.vue @@ -1,12 +1,10 @@ <script> -import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import SignInGitlabCom from './sign_in_gitlab_com.vue'; import SignInGitlabMultiversion from './sign_in_gitlab_multiversion/index.vue'; export default { name: 'SignInPage', components: { SignInGitlabCom, SignInGitlabMultiversion }, - mixins: [glFeatureFlagMixin()], props: { hasSubscriptions: { type: Boolean, diff --git a/app/assets/javascripts/jira_connect/subscriptions/store/actions.js b/app/assets/javascripts/jira_connect/subscriptions/store/actions.js index fff34e1d75d..3b8e4c7540b 100644 --- a/app/assets/javascripts/jira_connect/subscriptions/store/actions.js +++ b/app/assets/javascripts/jira_connect/subscriptions/store/actions.js @@ -14,8 +14,6 @@ import { SET_SUBSCRIPTIONS, SET_SUBSCRIPTIONS_LOADING, SET_SUBSCRIPTIONS_ERROR, - ADD_SUBSCRIPTION_LOADING, - ADD_SUBSCRIPTION_ERROR, SET_ALERT, SET_CURRENT_USER, SET_CURRENT_USER_ERROR, @@ -51,25 +49,17 @@ export const addSubscription = async ( { commit, state, dispatch }, { namespacePath, subscriptionsPath }, ) => { - try { - commit(ADD_SUBSCRIPTION_LOADING, true); - - await addJiraConnectSubscription(namespacePath, { - jwt: await getJwt(), - accessToken: state.accessToken, - }); + await addJiraConnectSubscription(namespacePath, { + jwt: await getJwt(), + accessToken: state.accessToken, + }); - commit(SET_ALERT, { - title: I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_TITLE, - message: I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_MESSAGE, - linkUrl: INTEGRATIONS_DOC_LINK, - variant: 'success', - }); + commit(SET_ALERT, { + title: I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_TITLE, + message: I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_MESSAGE, + linkUrl: INTEGRATIONS_DOC_LINK, + variant: 'success', + }); - dispatch('fetchSubscriptions', subscriptionsPath); - } catch (e) { - commit(ADD_SUBSCRIPTION_ERROR, e); - } finally { - commit(ADD_SUBSCRIPTION_LOADING, false); - } + dispatch('fetchSubscriptions', subscriptionsPath); }; diff --git a/app/assets/javascripts/jira_connect/subscriptions/store/mutation_types.js b/app/assets/javascripts/jira_connect/subscriptions/store/mutation_types.js index d4893fbcaf6..63aad27aeb6 100644 --- a/app/assets/javascripts/jira_connect/subscriptions/store/mutation_types.js +++ b/app/assets/javascripts/jira_connect/subscriptions/store/mutation_types.js @@ -4,9 +4,6 @@ export const SET_SUBSCRIPTIONS = 'SET_SUBSCRIPTIONS'; export const SET_SUBSCRIPTIONS_LOADING = 'SET_SUBSCRIPTIONS_LOADING'; export const SET_SUBSCRIPTIONS_ERROR = 'SET_SUBSCRIPTIONS_ERROR'; -export const ADD_SUBSCRIPTION_LOADING = 'ADD_SUBSCRIPTION_LOADING'; -export const ADD_SUBSCRIPTION_ERROR = 'ADD_SUBSCRIPTION_ERROR'; - export const SET_CURRENT_USER = 'SET_CURRENT_USER'; export const SET_CURRENT_USER_ERROR = 'SET_CURRENT_USER_ERROR'; diff --git a/app/assets/javascripts/jira_connect/subscriptions/store/mutations.js b/app/assets/javascripts/jira_connect/subscriptions/store/mutations.js index 60076c918fd..270ce9fab66 100644 --- a/app/assets/javascripts/jira_connect/subscriptions/store/mutations.js +++ b/app/assets/javascripts/jira_connect/subscriptions/store/mutations.js @@ -3,8 +3,6 @@ import { SET_SUBSCRIPTIONS, SET_SUBSCRIPTIONS_LOADING, SET_SUBSCRIPTIONS_ERROR, - ADD_SUBSCRIPTION_LOADING, - ADD_SUBSCRIPTION_ERROR, SET_CURRENT_USER, SET_CURRENT_USER_ERROR, SET_ACCESS_TOKEN, @@ -25,13 +23,6 @@ export default { state.subscriptionsError = subscriptionsError; }, - [ADD_SUBSCRIPTION_LOADING](state, loading) { - state.addSubscriptionLoading = loading; - }, - [ADD_SUBSCRIPTION_ERROR](state, error) { - state.addSubscriptionError = error; - }, - [SET_CURRENT_USER](state, currentUser) { state.currentUser = currentUser; }, diff --git a/app/assets/javascripts/jira_connect/subscriptions/store/state.js b/app/assets/javascripts/jira_connect/subscriptions/store/state.js index 82a8517b511..f35f79e3f53 100644 --- a/app/assets/javascripts/jira_connect/subscriptions/store/state.js +++ b/app/assets/javascripts/jira_connect/subscriptions/store/state.js @@ -10,9 +10,6 @@ export default function createState({ subscriptionsLoading, subscriptionsError: false, - addSubscriptionLoading: false, - addSubscriptionError: false, - currentUser, currentUserError: null, diff --git a/app/assets/javascripts/jira_connect/subscriptions/utils.js b/app/assets/javascripts/jira_connect/subscriptions/utils.js index 6db8b62d692..0b88e83f8da 100644 --- a/app/assets/javascripts/jira_connect/subscriptions/utils.js +++ b/app/assets/javascripts/jira_connect/subscriptions/utils.js @@ -1,5 +1,4 @@ import AccessorUtilities from '~/lib/utils/accessor'; -import { objectToQuery } from '~/lib/utils/url_utility'; import { ALERT_LOCALSTORAGE_KEY, BASE_URL_LOCALSTORAGE_KEY } from './constants'; const isFunction = (fn) => typeof fn === 'function'; @@ -76,18 +75,6 @@ export const getJwt = () => { }); }; -export const getLocation = () => { - return new Promise((resolve) => { - if (isFunction(AP?.getLocation)) { - AP.getLocation((location) => { - resolve(location); - }); - } else { - resolve(); - } - }); -}; - export const reloadPage = () => { if (isFunction(AP?.navigator?.reload)) { AP.navigator.reload(); @@ -101,17 +88,3 @@ export const sizeToParent = () => { AP.sizeToParent(); } }; - -export const getGitlabSignInURL = async (signInURL) => { - const location = await getLocation(); - - if (location) { - const queryParams = { - return_to: location, - }; - - return `${signInURL}?${objectToQuery(queryParams)}`; - } - - return signInURL; -}; diff --git a/app/assets/javascripts/notes/components/discussion_filter.vue b/app/assets/javascripts/notes/components/discussion_filter.vue index 21b48a2a666..692fd6cc500 100644 --- a/app/assets/javascripts/notes/components/discussion_filter.vue +++ b/app/assets/javascripts/notes/components/discussion_filter.vue @@ -1,5 +1,10 @@ <script> -import { GlDropdown, GlDropdownItem, GlDropdownDivider } from '@gitlab/ui'; +import { + GlIcon, + GlDisclosureDropdown, + GlDisclosureDropdownGroup, + GlDisclosureDropdownItem, +} from '@gitlab/ui'; import { mapGetters, mapActions } from 'vuex'; import { getLocationHash, doesHashExistInUrl } from '~/lib/utils/url_utility'; import { __ } from '~/locale'; @@ -25,9 +30,10 @@ const SORT_OPTIONS = [ export default { SORT_OPTIONS, components: { - GlDropdown, - GlDropdownItem, - GlDropdownDivider, + GlIcon, + GlDisclosureDropdown, + GlDisclosureDropdownGroup, + GlDisclosureDropdownItem, LocalStorageSync, }, mixins: [Tracking.mixin()], @@ -164,44 +170,64 @@ export default { as-string @input="setDiscussionSortDirection({ direction: $event })" /> - <gl-dropdown + <gl-disclosure-dropdown id="discussion-preferences-dropdown" class="full-width-mobile" data-qa-selector="discussion_preferences_dropdown" - :text="__('Sort or filter')" + :toggle-text="__('Sort or filter')" :disabled="isLoading" - right + placement="right" > - <div id="discussion-sort"> - <gl-dropdown-item + <gl-disclosure-dropdown-group id="discussion-sort"> + <gl-disclosure-dropdown-item v-for="{ text, key, cls } in $options.SORT_OPTIONS" :key="text" :class="cls" - is-check-item - :is-checked="isSortDropdownItemActive(key)" - @click="fetchSortedDiscussions(key)" + :is-selected="isSortDropdownItemActive(key)" + @action="fetchSortedDiscussions(key)" > - {{ text }} - </gl-dropdown-item> - </div> - <gl-dropdown-divider /> - <div + <template #list-item> + <gl-icon + name="mobile-issue-close" + data-testid="dropdown-item-checkbox" + :class="[ + 'gl-dropdown-item-check-icon', + { 'gl-visibility-hidden': !isSortDropdownItemActive(key) }, + 'gl-text-blue-400', + ]" + /> + {{ text }} + </template> + </gl-disclosure-dropdown-item> + </gl-disclosure-dropdown-group> + <gl-disclosure-dropdown-group id="discussion-filter" class="discussion-filter-container js-discussion-filter-container" + bordered > - <gl-dropdown-item + <gl-disclosure-dropdown-item v-for="filter in filters" :key="filter.value" - is-check-item - :is-checked="filter.value === currentValue" + :is-selected="filter.value === currentValue" :class="{ 'is-active': filter.value === currentValue }" :data-filter-type="filterType(filter.value)" data-qa-selector="filter_menu_item" - @click.prevent="selectFilter(filter.value)" + @action="selectFilter(filter.value)" > - {{ filter.title }} - </gl-dropdown-item> - </div> - </gl-dropdown> + <template #list-item> + <gl-icon + name="mobile-issue-close" + data-testid="dropdown-item-checkbox" + :class="[ + 'gl-dropdown-item-check-icon', + { 'gl-visibility-hidden': filter.value !== currentValue }, + 'gl-text-blue-400', + ]" + /> + {{ filter.title }} + </template> + </gl-disclosure-dropdown-item> + </gl-disclosure-dropdown-group> + </gl-disclosure-dropdown> </div> </template> diff --git a/app/assets/javascripts/pages/jira_connect/oauth_callbacks/index.js b/app/assets/javascripts/pages/jira_connect/oauth_callbacks/index.js index 3fe238dcb35..6e92f136e4d 100644 --- a/app/assets/javascripts/pages/jira_connect/oauth_callbacks/index.js +++ b/app/assets/javascripts/pages/jira_connect/oauth_callbacks/index.js @@ -1,3 +1,5 @@ +import { OAUTH_CALLBACK_MESSAGE_TYPE } from '~/jira_connect/subscriptions/constants'; + function getOriginURL() { const origin = new URL(window.opener.location); origin.hash = ''; @@ -7,7 +9,10 @@ function getOriginURL() { } function postMessageToJiraConnectApp(data) { - window.opener.postMessage(data, getOriginURL().toString()); + window.opener.postMessage( + { ...data, type: OAUTH_CALLBACK_MESSAGE_TYPE }, + getOriginURL().toString(), + ); } function initOAuthCallbacks() { diff --git a/app/assets/javascripts/related_issues/components/related_issues_list.vue b/app/assets/javascripts/related_issues/components/related_issues_list.vue index 4429c1beb00..6a047ff7e9d 100644 --- a/app/assets/javascripts/related_issues/components/related_issues_list.vue +++ b/app/assets/javascripts/related_issues/components/related_issues_list.vue @@ -146,6 +146,7 @@ export default { :work-item-type="issue.type" event-namespace="relatedIssue" data-qa-selector="related_issuable_content" + class="gl-mx-n2" @relatedIssueRemoveRequest="$emit('relatedIssueRemoveRequest', $event)" /> </li> diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss index d033a076832..febb597e26e 100644 --- a/app/assets/stylesheets/framework/common.scss +++ b/app/assets/stylesheets/framework/common.scss @@ -474,7 +474,8 @@ li.note { width: 100%; > .dropdown-menu, - > .btn { + > .btn, + > .gl-new-dropdown-toggle > .gl-button-text { width: 100%; } } diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index 96d78034ad6..dff1c04311d 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -22,17 +22,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController :preferences, :update, :reset_health_check_token ] - feature_category :metrics, [ - :create_self_monitoring_project, - :status_create_self_monitoring_project, - :delete_self_monitoring_project, - :status_delete_self_monitoring_project - ] urgency :low, [ - :create_self_monitoring_project, - :status_create_self_monitoring_project, - :delete_self_monitoring_project, - :status_delete_self_monitoring_project, :reset_error_tracking_access_token ] @@ -124,91 +114,8 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController redirect_to ::Gitlab::LetsEncrypt.terms_of_service_url end - # Specs are in spec/requests/self_monitoring_project_spec.rb - def create_self_monitoring_project - job_id = SelfMonitoringProjectCreateWorker.with_status.perform_async # rubocop:disable CodeReuse/Worker - - render status: :accepted, json: { - job_id: job_id, - monitor_status: status_create_self_monitoring_project_admin_application_settings_path - } - end - - # Specs are in spec/requests/self_monitoring_project_spec.rb - def status_create_self_monitoring_project - job_id = params[:job_id].to_s - - unless job_id.length <= PARAM_JOB_ID_MAX_SIZE - return render status: :bad_request, json: { - message: format(_('Parameter "job_id" cannot exceed length of %{job_id_max_size}'), job_id_max_size: PARAM_JOB_ID_MAX_SIZE) - } - end - - if SelfMonitoringProjectCreateWorker.in_progress?(job_id) # rubocop:disable CodeReuse/Worker - ::Gitlab::PollingInterval.set_header(response, interval: 3_000) - - return render status: :accepted, json: { - message: _('Job to create self-monitoring project is in progress') - } - end - - return render status: :ok, json: self_monitoring_data if @application_setting.self_monitoring_project_id.present? - - render status: :bad_request, json: { - message: _('Self-monitoring project does not exist. Please check logs ' \ - 'for any error messages') - } - end - - # Specs are in spec/requests/self_monitoring_project_spec.rb - def delete_self_monitoring_project - job_id = SelfMonitoringProjectDeleteWorker.with_status.perform_async # rubocop:disable CodeReuse/Worker - - render status: :accepted, json: { - job_id: job_id, - monitor_status: status_delete_self_monitoring_project_admin_application_settings_path - } - end - - # Specs are in spec/requests/self_monitoring_project_spec.rb - def status_delete_self_monitoring_project - job_id = params[:job_id].to_s - - unless job_id.length <= PARAM_JOB_ID_MAX_SIZE - return render status: :bad_request, json: { - message: format(_('Parameter "job_id" cannot exceed length of %{job_id_max_size}'), job_id_max_size: PARAM_JOB_ID_MAX_SIZE) - } - end - - if SelfMonitoringProjectDeleteWorker.in_progress?(job_id) # rubocop:disable CodeReuse/Worker - ::Gitlab::PollingInterval.set_header(response, interval: 3_000) - - return render status: :accepted, json: { - message: _('Job to delete self-monitoring project is in progress') - } - end - - if @application_setting.self_monitoring_project_id.nil? - return render status: :ok, json: { - message: _('Self-monitoring project has been successfully deleted') - } - end - - render status: :bad_request, json: { - message: _('Self-monitoring project was not deleted. Please check logs ' \ - 'for any error messages') - } - end - private - def self_monitoring_data - { - project_id: @application_setting.self_monitoring_project_id, - project_full_path: @application_setting.self_monitoring_project&.full_path - } - end - def set_application_setting @application_setting = ApplicationSetting.current_without_cache @plans = Plan.all diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index a7694c58588..05f679df2c9 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -542,28 +542,6 @@ module ApplicationSettingsHelper Rack::Attack.throttles.key?('protected paths') end - def self_monitoring_project_data - { - 'create_self_monitoring_project_path' => - create_self_monitoring_project_admin_application_settings_path, - - 'status_create_self_monitoring_project_path' => - status_create_self_monitoring_project_admin_application_settings_path, - - 'delete_self_monitoring_project_path' => - delete_self_monitoring_project_admin_application_settings_path, - - 'status_delete_self_monitoring_project_path' => - status_delete_self_monitoring_project_admin_application_settings_path, - - 'self_monitoring_project_exists' => - Gitlab::CurrentSettings.self_monitoring_project.present?.to_s, - - 'self_monitoring_project_full_path' => - Gitlab::CurrentSettings.self_monitoring_project&.full_path - } - end - def valid_runner_registrars Gitlab::CurrentSettings.valid_runner_registrars end diff --git a/app/helpers/jira_connect_helper.rb b/app/helpers/jira_connect_helper.rb index af2c09554f0..5cf68db0611 100644 --- a/app/helpers/jira_connect_helper.rb +++ b/app/helpers/jira_connect_helper.rb @@ -7,9 +7,7 @@ module JiraConnectHelper { groups_path: api_v4_groups_path(params: { min_access_level: Gitlab::Access::MAINTAINER, skip_groups: skip_groups }), subscriptions: subscriptions.map { |s| serialize_subscription(s) }.to_json, - add_subscriptions_path: jira_connect_subscriptions_path, subscriptions_path: jira_connect_subscriptions_path(format: :json), - users_path: current_user ? nil : jira_connect_users_path, # users_path is used to determine if user is signed in gitlab_user_path: current_user ? user_path(current_user) : nil, oauth_metadata: jira_connect_oauth_data(installation).to_json, public_key_storage_enabled: Gitlab::CurrentSettings.jira_connect_public_key_storage_enabled? diff --git a/app/services/metrics/dashboard/clone_dashboard_service.rb b/app/services/metrics/dashboard/clone_dashboard_service.rb index d9bd9423a1b..18623ad336d 100644 --- a/app/services/metrics/dashboard/clone_dashboard_service.rb +++ b/app/services/metrics/dashboard/clone_dashboard_service.rb @@ -16,10 +16,6 @@ module Metrics ::Gitlab::Metrics::Dashboard::Stages::CustomMetricsInserter ].freeze, - ::Metrics::Dashboard::SelfMonitoringDashboardService::DASHBOARD_PATH => [ - ::Gitlab::Metrics::Dashboard::Stages::CustomMetricsInserter - ].freeze, - ::Metrics::Dashboard::ClusterDashboardService::DASHBOARD_PATH => [ ::Gitlab::Metrics::Dashboard::Stages::CommonMetricsInserter ].freeze diff --git a/config/routes/admin.rb b/config/routes/admin.rb index 0ebf13ac8d0..6130f7c2fe2 100644 --- a/config/routes/admin.rb +++ b/config/routes/admin.rb @@ -156,11 +156,6 @@ namespace :admin do match :general, :integrations, :repository, :ci_cd, :reporting, :metrics_and_profiling, :network, :preferences, via: [:get, :patch] get :lets_encrypt_terms_of_service - post :create_self_monitoring_project - get :status_create_self_monitoring_project - delete :delete_self_monitoring_project - get :status_delete_self_monitoring_project - get :service_usage_data resource :appearances, only: [:show, :create, :update], path: 'appearance', module: 'application_settings' do diff --git a/doc/user/application_security/secret_detection/post_processing.md b/doc/user/application_security/secret_detection/post_processing.md index 3657e3cd024..a898a63e33b 100644 --- a/doc/user/application_security/secret_detection/post_processing.md +++ b/doc/user/application_security/secret_detection/post_processing.md @@ -4,26 +4,24 @@ group: Static Analysis info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments --- -# Secret Detection post-processing and revocation **(ULTIMATE)** +# Automatic response to leaked secrets **(ULTIMATE)** -> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4639) in GitLab 13.6. -> - [Disabled by default for GitLab personal access tokens](https://gitlab.com/gitlab-org/gitlab/-/issues/371658) in GitLab 15.6 [with a flag](../../../administration/feature_flags.md) named `gitlab_pat_auto_revocation`. Available to GitLab.com only. -> - [Enabled by default for GitLab personal access tokens](https://gitlab.com/gitlab-org/gitlab/-/issues/371658) in GitLab 15.9 +> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4639) in GitLab 13.6. -GitLab.com and self-managed supports running post-processing hooks after detecting a secret. These -hooks can perform actions, like notifying the vendor that issued the secret. -The vendor can then confirm the credentials and take remediation actions, like: +GitLab Secret Detection automatically responds when it finds certain types of leaked secrets. +Automatic responses can: -- Revoking a secret. -- Reissuing a secret. -- Notifying the creator of the secret. +- Automatically revoke the secret. +- Notify the partner that issued the secret. The partner can then revoke the secret, notify its owner, or otherwise protect against abuse. -GitLab supports post-processing for the following vendors and secrets: +## Supported secret types and actions -| Vendor | Secret | GitLab.com | Self-managed | +GitLab supports automatic response for the following types of secrets: + +| Secret type | Action taken | Supported on GitLab.com | Supported in self-managed | | ----- | --- | --- | --- | -| GitLab | [Personal access tokens](../../profile/personal_access_tokens.md) | ✅ | ✅ 15.9 and later | -| Amazon Web Services (AWS) | [IAM access keys](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html) | ✅ | ⚙ | +| GitLab [Personal access tokens](../../profile/personal_access_tokens.md) | Immediately revoke token, send email to owner | ✅ | ✅ [15.9 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/371658) | +| Amazon Web Services (AWS) [IAM access keys](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html) | Notify AWS | ✅ | ⚙ | **Component legend** diff --git a/lib/gitlab/database.rb b/lib/gitlab/database.rb index f77169f6d2b..57caf1b07e6 100644 --- a/lib/gitlab/database.rb +++ b/lib/gitlab/database.rb @@ -35,7 +35,7 @@ module Gitlab MAX_TEXT_SIZE_LIMIT = 1_000_000 # Migrations before this version may have been removed - MIN_SCHEMA_GITLAB_VERSION = '15.0' + MIN_SCHEMA_GITLAB_VERSION = '15.11' # Schema we store dynamically managed partitions in (e.g. for time partitioning) DYNAMIC_PARTITIONS_SCHEMA = :gitlab_partitions_dynamic diff --git a/lib/gitlab/metrics/dashboard/finder.rb b/lib/gitlab/metrics/dashboard/finder.rb index a4964ae0ebc..12f7c347b2d 100644 --- a/lib/gitlab/metrics/dashboard/finder.rb +++ b/lib/gitlab/metrics/dashboard/finder.rb @@ -64,7 +64,7 @@ module Gitlab # display_name: String, # default: Boolean }] def find_all_paths(project) - dashboards = user_facing_dashboard_services(project).flat_map do |service| + dashboards = user_facing_dashboard_services.flat_map do |service| service.all_dashboard_paths(project) end @@ -73,19 +73,8 @@ module Gitlab private - def user_facing_dashboard_services(project) - predefined_dashboard_services_for(project) + [project_service] - end - - def predefined_dashboard_services_for(project) - # Only list the self-monitoring dashboard on the self-monitoring project, - # since it is the only dashboard (at time of writing) that shows data - # about GitLab itself. - if project.self_monitoring? - return [self_monitoring_service] - end - - PREDEFINED_DASHBOARD_LIST + def user_facing_dashboard_services + PREDEFINED_DASHBOARD_LIST + [project_service] end def system_service @@ -96,10 +85,6 @@ module Gitlab ::Metrics::Dashboard::CustomDashboardService end - def self_monitoring_service - ::Metrics::Dashboard::SelfMonitoringDashboardService - end - def service_for(options) Gitlab::Metrics::Dashboard::ServiceSelector.call(options) end diff --git a/lib/gitlab/metrics/dashboard/service_selector.rb b/lib/gitlab/metrics/dashboard/service_selector.rb index 6d4b49676e5..67bf4ce7e9a 100644 --- a/lib/gitlab/metrics/dashboard/service_selector.rb +++ b/lib/gitlab/metrics/dashboard/service_selector.rb @@ -23,7 +23,6 @@ module Gitlab ::Metrics::Dashboard::DefaultEmbedService, ::Metrics::Dashboard::SystemDashboardService, ::Metrics::Dashboard::PodDashboardService, - ::Metrics::Dashboard::SelfMonitoringDashboardService, ::Metrics::Dashboard::CustomDashboardService ].freeze diff --git a/locale/gitlab.pot b/locale/gitlab.pot index ed0a33684c1..9815086b073 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -25041,12 +25041,6 @@ msgstr "" msgid "Job logs and artifacts" msgstr "" -msgid "Job to create self-monitoring project is in progress" -msgstr "" - -msgid "Job to delete self-monitoring project is in progress" -msgstr "" - msgid "Job was retried" msgstr "" @@ -31727,9 +31721,6 @@ msgstr "" msgid "Parameter" msgstr "" -msgid "Parameter \"job_id\" cannot exceed length of %{job_id_max_size}" -msgstr "" - msgid "Parent" msgstr "" @@ -40821,15 +40812,6 @@ msgstr "" msgid "Self-monitoring project does not exist" msgstr "" -msgid "Self-monitoring project does not exist. Please check logs for any error messages" -msgstr "" - -msgid "Self-monitoring project has been successfully deleted" -msgstr "" - -msgid "Self-monitoring project was not deleted. Please check logs for any error messages" -msgstr "" - msgid "Self-monitoring was %{deprecation}deprecated%{link_end} in GitLab 14.9, and is %{removal}scheduled for removal%{link_end} in GitLab 16.0. For information on a possible replacement, %{opstrace}learn more about Opstrace%{link_end}." msgstr "" diff --git a/spec/features/issues/user_sorts_issue_comments_spec.rb b/spec/features/issues/user_sorts_issue_comments_spec.rb index ca52e620ea7..153066343f2 100644 --- a/spec/features/issues/user_sorts_issue_comments_spec.rb +++ b/spec/features/issues/user_sorts_issue_comments_spec.rb @@ -16,9 +16,8 @@ RSpec.describe 'Comment sort direction', feature_category: :team_planning do it 'saves sort order' do # open dropdown, and select 'Newest first' page.within('.issuable-details') do - find('#discussion-preferences-dropdown').click + click_button('Sort or filter') click_button('Oldest first') - find('#discussion-preferences-dropdown').click click_button('Newest first') end diff --git a/spec/frontend/bootstrap_linked_tabs_spec.js b/spec/frontend/bootstrap_linked_tabs_spec.js index 5ee1ca32141..f900cd9da3b 100644 --- a/spec/frontend/bootstrap_linked_tabs_spec.js +++ b/spec/frontend/bootstrap_linked_tabs_spec.js @@ -1,9 +1,10 @@ -import { loadHTMLFixture, resetHTMLFixture } from 'helpers/fixtures'; +import htmlLinkedTabs from 'test_fixtures_static/linked_tabs.html'; +import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures'; import LinkedTabs from '~/lib/utils/bootstrap_linked_tabs'; describe('Linked Tabs', () => { beforeEach(() => { - loadHTMLFixture('static/linked_tabs.html'); + setHTMLFixture(htmlLinkedTabs); }); afterEach(() => { diff --git a/spec/frontend/jira_connect/subscriptions/api_spec.js b/spec/frontend/jira_connect/subscriptions/api_spec.js index 5a28c6d9789..36e2c7bbab2 100644 --- a/spec/frontend/jira_connect/subscriptions/api_spec.js +++ b/spec/frontend/jira_connect/subscriptions/api_spec.js @@ -1,7 +1,6 @@ import MockAdapter from 'axios-mock-adapter'; import { axiosInstance, - addSubscription, removeSubscription, fetchGroups, getCurrentUser, @@ -19,7 +18,6 @@ describe('JiraConnect API', () => { let axiosMock; let response; - const mockAddPath = 'addPath'; const mockRemovePath = 'removePath'; const mockNamespace = 'namespace'; const mockJwt = 'jwt'; @@ -36,29 +34,6 @@ describe('JiraConnect API', () => { response = null; }); - describe('addSubscription', () => { - const makeRequest = () => addSubscription(mockAddPath, mockNamespace); - - it('returns success response', async () => { - jest.spyOn(axiosInstance, 'post'); - axiosMock - .onPost(mockAddPath, { - jwt: mockJwt, - namespace_path: mockNamespace, - }) - .replyOnce(HTTP_STATUS_OK, mockResponse); - - response = await makeRequest(); - - expect(getJwt).toHaveBeenCalled(); - expect(axiosInstance.post).toHaveBeenCalledWith(mockAddPath, { - jwt: mockJwt, - namespace_path: mockNamespace, - }); - expect(response.data).toEqual(mockResponse); - }); - }); - describe('removeSubscription', () => { const makeRequest = () => removeSubscription(mockRemovePath); diff --git a/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item_spec.js b/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item_spec.js index 9b54c6d5c49..c5035a12bd1 100644 --- a/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item_spec.js +++ b/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item_spec.js @@ -10,8 +10,6 @@ describe('GroupsListItem', () => { let wrapper; let store; - const mockAddSubscriptionsPath = '/addSubscriptionsPath'; - const createComponent = ({ mountFn = shallowMount, provide } = {}) => { store = createStore(); @@ -23,7 +21,6 @@ describe('GroupsListItem', () => { group: mockGroup1, }, provide: { - addSubscriptionsPath: mockAddSubscriptionsPath, ...provide, }, }); diff --git a/spec/frontend/jira_connect/subscriptions/components/sign_in_legacy_button_spec.js b/spec/frontend/jira_connect/subscriptions/components/sign_in_legacy_button_spec.js deleted file mode 100644 index 0dadec598e4..00000000000 --- a/spec/frontend/jira_connect/subscriptions/components/sign_in_legacy_button_spec.js +++ /dev/null @@ -1,54 +0,0 @@ -import { GlButton } from '@gitlab/ui'; -import { shallowMount } from '@vue/test-utils'; -import { getGitlabSignInURL } from '~/jira_connect/subscriptions/utils'; -import SignInLegacyButton from '~/jira_connect/subscriptions/components/sign_in_legacy_button.vue'; -import waitForPromises from 'helpers/wait_for_promises'; - -const MOCK_USERS_PATH = '/user'; - -jest.mock('~/jira_connect/subscriptions/utils'); - -describe('SignInLegacyButton', () => { - let wrapper; - - const createComponent = ({ slots } = {}) => { - wrapper = shallowMount(SignInLegacyButton, { - propsData: { - usersPath: MOCK_USERS_PATH, - }, - slots, - }); - }; - - const findButton = () => wrapper.findComponent(GlButton); - - it('displays a button', () => { - createComponent(); - - expect(findButton().exists()).toBe(true); - expect(findButton().text()).toBe(SignInLegacyButton.i18n.defaultButtonText); - }); - - describe.each` - expectedHref - ${MOCK_USERS_PATH} - ${`${MOCK_USERS_PATH}?return_to=${encodeURIComponent('https://test.jira.com')}`} - `('when getGitlabSignInURL resolves with `$expectedHref`', ({ expectedHref }) => { - it(`sets button href to ${expectedHref}`, async () => { - getGitlabSignInURL.mockResolvedValue(expectedHref); - createComponent(); - - await waitForPromises(); - - expect(findButton().attributes('href')).toBe(expectedHref); - }); - }); - - describe('with slot', () => { - const mockSlotContent = 'custom button content!'; - it('renders slot content in button', () => { - createComponent({ slots: { default: mockSlotContent } }); - expect(wrapper.text()).toMatchInterpolatedText(mockSlotContent); - }); - }); -}); diff --git a/spec/frontend/jira_connect/subscriptions/components/sign_in_oauth_button_spec.js b/spec/frontend/jira_connect/subscriptions/components/sign_in_oauth_button_spec.js index 9d39b82c05f..ee272d55e0e 100644 --- a/spec/frontend/jira_connect/subscriptions/components/sign_in_oauth_button_spec.js +++ b/spec/frontend/jira_connect/subscriptions/components/sign_in_oauth_button_spec.js @@ -157,6 +157,7 @@ describe('SignInOauthButton', () => { const mockEvent = { origin: messageOrigin, data: { + type: 'jiraConnectOauthCallback', state: messageState, code: '1234', }, @@ -182,6 +183,7 @@ describe('SignInOauthButton', () => { const mockEvent = { origin: window.origin, data: { + type: 'jiraConnectOauthCallback', state: mockOauthMetadata.state, code: '1234', }, diff --git a/spec/frontend/jira_connect/subscriptions/components/user_link_spec.js b/spec/frontend/jira_connect/subscriptions/components/user_link_spec.js index 20cbcda8661..a10e352ed85 100644 --- a/spec/frontend/jira_connect/subscriptions/components/user_link_spec.js +++ b/spec/frontend/jira_connect/subscriptions/components/user_link_spec.js @@ -4,10 +4,6 @@ import SignInOauthButton from '~/jira_connect/subscriptions/components/sign_in_o import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; -jest.mock('~/jira_connect/subscriptions/utils', () => ({ - getGitlabSignInURL: jest.fn().mockImplementation((path) => Promise.resolve(path)), -})); - describe('UserLink', () => { let wrapper; diff --git a/spec/frontend/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_com_spec.js b/spec/frontend/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_com_spec.js index cb9eb5f67f9..4cfd925db34 100644 --- a/spec/frontend/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_com_spec.js +++ b/spec/frontend/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_com_spec.js @@ -1,7 +1,6 @@ import { shallowMount } from '@vue/test-utils'; import SignInGitlabCom from '~/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_com.vue'; -import SignInLegacyButton from '~/jira_connect/subscriptions/components/sign_in_legacy_button.vue'; import SignInOauthButton from '~/jira_connect/subscriptions/components/sign_in_oauth_button.vue'; import SubscriptionsList from '~/jira_connect/subscriptions/components/subscriptions_list.vue'; import createStore from '~/jira_connect/subscriptions/store'; @@ -9,10 +8,8 @@ import { I18N_DEFAULT_SIGN_IN_BUTTON_TEXT } from '~/jira_connect/subscriptions/c jest.mock('~/jira_connect/subscriptions/utils'); -const mockUsersPath = '/test'; const defaultProvide = { oauthMetadata: {}, - usersPath: mockUsersPath, }; describe('SignInGitlabCom', () => { @@ -32,7 +29,6 @@ describe('SignInGitlabCom', () => { }, propsData: props, stubs: { - SignInLegacyButton, SignInOauthButton, }, }); diff --git a/spec/frontend/jira_connect/subscriptions/store/actions_spec.js b/spec/frontend/jira_connect/subscriptions/store/actions_spec.js index 5e3c30269b5..e53c3e766d2 100644 --- a/spec/frontend/jira_connect/subscriptions/store/actions_spec.js +++ b/spec/frontend/jira_connect/subscriptions/store/actions_spec.js @@ -117,7 +117,7 @@ describe('JiraConnect actions', () => { }); describe('when API request succeeds', () => { - it('commits the SET_ACCESS_TOKEN and SET_CURRENT_USER mutations', async () => { + it('commits the SET_ALERT mutation', async () => { jest.spyOn(api, 'addJiraConnectSubscription').mockResolvedValue({ success: true }); await testAction( @@ -125,7 +125,6 @@ describe('JiraConnect actions', () => { { namespacePath: mockNamespace, subscriptionsPath: mockSubscriptionsPath }, mockedState, [ - { type: types.ADD_SUBSCRIPTION_LOADING, payload: true }, { type: types.SET_ALERT, payload: { @@ -135,7 +134,6 @@ describe('JiraConnect actions', () => { variant: 'success', }, }, - { type: types.ADD_SUBSCRIPTION_LOADING, payload: false }, ], [{ type: 'fetchSubscriptions', payload: mockSubscriptionsPath }], ); @@ -148,20 +146,18 @@ describe('JiraConnect actions', () => { }); describe('when API request fails', () => { - it('commits the SET_CURRENT_USER_ERROR mutation', async () => { + it('does not commit the SET_ALERT mutation', () => { jest.spyOn(api, 'addJiraConnectSubscription').mockRejectedValue(); - await testAction( + // We need the empty catch(), since we are testing rejecting the promise, + // which would otherwise cause the test to fail. + testAction( addSubscription, - mockNamespace, + { namespacePath: mockNamespace, subscriptionsPath: mockSubscriptionsPath }, mockedState, - [ - { type: types.ADD_SUBSCRIPTION_LOADING, payload: true }, - { type: types.ADD_SUBSCRIPTION_ERROR }, - { type: types.ADD_SUBSCRIPTION_LOADING, payload: false }, - ], [], - ); + [], + ).catch(() => {}); }); }); }); diff --git a/spec/frontend/jira_connect/subscriptions/store/mutations_spec.js b/spec/frontend/jira_connect/subscriptions/store/mutations_spec.js index aeb136a76b9..e41bcec19b7 100644 --- a/spec/frontend/jira_connect/subscriptions/store/mutations_spec.js +++ b/spec/frontend/jira_connect/subscriptions/store/mutations_spec.js @@ -51,22 +51,6 @@ describe('JiraConnect store mutations', () => { }); }); - describe('ADD_SUBSCRIPTION_LOADING', () => { - it('sets addSubscriptionLoading', () => { - mutations.ADD_SUBSCRIPTION_LOADING(localState, true); - - expect(localState.addSubscriptionLoading).toBe(true); - }); - }); - - describe('ADD_SUBSCRIPTION_ERROR', () => { - it('sets addSubscriptionError', () => { - mutations.ADD_SUBSCRIPTION_ERROR(localState, true); - - expect(localState.addSubscriptionError).toBe(true); - }); - }); - describe('SET_CURRENT_USER', () => { it('sets currentUser', () => { const mockUser = { name: 'root' }; diff --git a/spec/frontend/jira_connect/subscriptions/utils_spec.js b/spec/frontend/jira_connect/subscriptions/utils_spec.js index 762d9eb3443..d1588dbad2c 100644 --- a/spec/frontend/jira_connect/subscriptions/utils_spec.js +++ b/spec/frontend/jira_connect/subscriptions/utils_spec.js @@ -5,10 +5,8 @@ import { persistAlert, retrieveAlert, getJwt, - getLocation, reloadPage, sizeToParent, - getGitlabSignInURL, } from '~/jira_connect/subscriptions/utils'; describe('JiraConnect utils', () => { @@ -69,29 +67,6 @@ describe('JiraConnect utils', () => { }); }); - describe('getLocation', () => { - const mockLocation = 'test/location'; - const getLocationSpy = jest.fn((callback) => callback(mockLocation)); - - it('resolves to the function call when AP.getLocation is a function', async () => { - global.AP = { - getLocation: getLocationSpy, - }; - - const location = await getLocation(); - - expect(getLocationSpy).toHaveBeenCalled(); - expect(location).toBe(mockLocation); - }); - - it('resolves to undefined when AP.getLocation is not a function', async () => { - const location = await getLocation(); - - expect(getLocationSpy).not.toHaveBeenCalled(); - expect(location).toBeUndefined(); - }); - }); - describe('reloadPage', () => { const reloadSpy = jest.fn(); @@ -138,25 +113,4 @@ describe('JiraConnect utils', () => { }); }); }); - - describe('getGitlabSignInURL', () => { - const mockSignInURL = 'https://gitlab.com/sign_in'; - - it.each` - returnTo | expectResult - ${undefined} | ${mockSignInURL} - ${''} | ${mockSignInURL} - ${'/test/location'} | ${`${mockSignInURL}?return_to=${encodeURIComponent('/test/location')}`} - `( - 'returns `$expectResult` when `AP.getLocation` resolves to `$returnTo`', - async ({ returnTo, expectResult }) => { - global.AP = { - getLocation: jest.fn().mockImplementation((cb) => cb(returnTo)), - }; - - const url = await getGitlabSignInURL(mockSignInURL); - expect(url).toBe(expectResult); - }, - ); - }); }); diff --git a/spec/frontend/merge_request_spec.js b/spec/frontend/merge_request_spec.js index be16b5ebfd2..6f80f8e6aab 100644 --- a/spec/frontend/merge_request_spec.js +++ b/spec/frontend/merge_request_spec.js @@ -1,6 +1,8 @@ import MockAdapter from 'axios-mock-adapter'; import $ from 'jquery'; -import { loadHTMLFixture, resetHTMLFixture } from 'helpers/fixtures'; +import htmlMergeRequestWithTaskList from 'test_fixtures/merge_requests/merge_request_with_task_list.html'; +import htmlMergeRequestOfCurrentUser from 'test_fixtures/merge_requests/merge_request_of_current_user.html'; +import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures'; import { TEST_HOST } from 'spec/test_constants'; import waitForPromises from 'helpers/wait_for_promises'; import { createAlert } from '~/alert'; @@ -16,7 +18,7 @@ describe('MergeRequest', () => { let mock; beforeEach(() => { - loadHTMLFixture('merge_requests/merge_request_with_task_list.html'); + setHTMLFixture(htmlMergeRequestWithTaskList); jest.spyOn(axios, 'patch'); mock = new MockAdapter(axios); @@ -112,7 +114,7 @@ describe('MergeRequest', () => { describe('hideCloseButton', () => { describe('merge request of current_user', () => { beforeEach(() => { - loadHTMLFixture('merge_requests/merge_request_of_current_user.html'); + setHTMLFixture(htmlMergeRequestOfCurrentUser); test.el = document.querySelector('.js-issuable-actions'); MergeRequest.hideCloseButton(); }); diff --git a/spec/frontend/notes/components/discussion_filter_spec.js b/spec/frontend/notes/components/discussion_filter_spec.js index 28e5e65c177..7d8347b20d4 100644 --- a/spec/frontend/notes/components/discussion_filter_spec.js +++ b/spec/frontend/notes/components/discussion_filter_spec.js @@ -1,4 +1,4 @@ -import { GlDropdown, GlDropdownItem } from '@gitlab/ui'; +import { GlDisclosureDropdown, GlDisclosureDropdownItem } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; import Vue, { nextTick } from 'vue'; import AxiosMockAdapter from 'axios-mock-adapter'; @@ -34,7 +34,8 @@ describe('DiscussionFilter component', () => { const filterDiscussion = jest.fn(); const findFilter = (filterType) => - wrapper.find(`.dropdown-item[data-filter-type="${filterType}"]`); + wrapper.find(`.gl-new-dropdown-item[data-filter-type="${filterType}"]`); + const findGlDisclosureDropdownItem = () => wrapper.findComponent(GlDisclosureDropdownItem); const findLocalStorageSync = () => wrapper.findComponent(LocalStorageSync); @@ -109,7 +110,7 @@ describe('DiscussionFilter component', () => { describe('when the dropdown is clicked', () => { it('calls the right actions', () => { - wrapper.find('.js-newest-first').vm.$emit('click'); + wrapper.find('.js-newest-first').vm.$emit('action'); expect(store.dispatch).toHaveBeenCalledWith('setDiscussionSortDirection', { direction: DESC, @@ -130,7 +131,7 @@ describe('DiscussionFilter component', () => { describe('when the dropdown item is clicked', () => { it('calls the right actions', () => { - wrapper.find('.js-oldest-first').vm.$emit('click'); + wrapper.find('.js-oldest-first').vm.$emit('action'); expect(store.dispatch).toHaveBeenCalledWith('setDiscussionSortDirection', { direction: ASC, @@ -140,8 +141,8 @@ describe('DiscussionFilter component', () => { }); }); - it('sets is-checked to true on the active button in the dropdown', () => { - expect(wrapper.find('.js-newest-first').props('isChecked')).toBe(true); + it('sets is-selected to true on the active button in the dropdown', () => { + expect(findGlDisclosureDropdownItem().attributes('is-selected')).toBe('true'); }); }); }); @@ -152,13 +153,13 @@ describe('DiscussionFilter component', () => { }); it('renders the all filters', () => { - expect(wrapper.findAll('.discussion-filter-container .dropdown-item').length).toBe( + expect(wrapper.findAll('.discussion-filter-container .gl-new-dropdown-item').length).toBe( discussionFiltersMock.length, ); }); it('renders the default selected item', () => { - expect(wrapper.find('.discussion-filter-container .dropdown-item').text().trim()).toBe( + expect(wrapper.find('.discussion-filter-container .gl-new-dropdown-item').text().trim()).toBe( discussionFiltersMock[0].title, ); }); @@ -166,19 +167,19 @@ describe('DiscussionFilter component', () => { it('disables the dropdown when discussions are loading', () => { store.state.isLoading = true; - expect(wrapper.findComponent(GlDropdown).props('disabled')).toBe(true); + expect(wrapper.findComponent(GlDisclosureDropdown).props('disabled')).toBe(true); }); it('updates to the selected item', () => { const filterItem = findFilter(DISCUSSION_FILTER_TYPES.ALL); - filterItem.trigger('click'); + filterItem.vm.$emit('action'); expect(filterItem.text().trim()).toBe('Show all activity'); }); it('only updates when selected filter changes', () => { - findFilter(DISCUSSION_FILTER_TYPES.ALL).trigger('click'); + findFilter(DISCUSSION_FILTER_TYPES.ALL).vm.$emit('action'); expect(filterDiscussion).not.toHaveBeenCalled(); }); @@ -186,19 +187,19 @@ describe('DiscussionFilter component', () => { it('disables timeline view if it was enabled', () => { store.state.isTimelineEnabled = true; - findFilter(DISCUSSION_FILTER_TYPES.HISTORY).trigger('click'); + findFilter(DISCUSSION_FILTER_TYPES.HISTORY).vm.$emit('action'); expect(store.state.isTimelineEnabled).toBe(false); }); it('disables commenting when "Show history only" filter is applied', () => { - findFilter(DISCUSSION_FILTER_TYPES.HISTORY).trigger('click'); + findFilter(DISCUSSION_FILTER_TYPES.HISTORY).vm.$emit('action'); expect(store.state.commentsDisabled).toBe(true); }); it('enables commenting when "Show history only" filter is not applied', () => { - findFilter(DISCUSSION_FILTER_TYPES.ALL).trigger('click'); + findFilter(DISCUSSION_FILTER_TYPES.ALL).vm.$emit('action'); expect(store.state.commentsDisabled).toBe(false); }); @@ -229,7 +230,7 @@ describe('DiscussionFilter component', () => { }); describe('URL with Links to notes', () => { - const findDropdownItems = () => wrapper.findAllComponents(GlDropdownItem); + const findGlDisclosureDropdownItems = () => wrapper.findAllComponents(GlDisclosureDropdownItem); afterEach(() => { window.location.hash = ''; @@ -240,7 +241,7 @@ describe('DiscussionFilter component', () => { wrapper = mountComponent(); await nextTick(); - const filtered = findDropdownItems().filter((el) => el.classes('is-active')); + const filtered = findGlDisclosureDropdownItems().filter((el) => el.classes('is-active')); expect(filtered).toHaveLength(1); expect(filtered.at(0).text()).toBe(discussionFiltersMock[0].title); @@ -251,7 +252,7 @@ describe('DiscussionFilter component', () => { wrapper = mountComponent(); await nextTick(); - const filtered = findDropdownItems().filter((el) => el.classes('is-active')); + const filtered = findGlDisclosureDropdownItems().filter((el) => el.classes('is-active')); expect(filtered).toHaveLength(1); expect(filtered.at(0).text()).toBe(discussionFiltersMock[0].title); diff --git a/spec/frontend/settings_panels_spec.js b/spec/frontend/settings_panels_spec.js index d59e1a20b27..1ef91181e1d 100644 --- a/spec/frontend/settings_panels_spec.js +++ b/spec/frontend/settings_panels_spec.js @@ -1,10 +1,11 @@ import $ from 'jquery'; -import { loadHTMLFixture, resetHTMLFixture } from 'helpers/fixtures'; +import htmlGroupsEdit from 'test_fixtures/groups/edit.html'; +import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures'; import initSettingsPanels, { isExpanded } from '~/settings_panels'; describe('Settings Panels', () => { beforeEach(() => { - loadHTMLFixture('groups/edit.html'); + setHTMLFixture(htmlGroupsEdit); }); afterEach(() => { diff --git a/spec/helpers/application_settings_helper_spec.rb b/spec/helpers/application_settings_helper_spec.rb index 93db4661c82..91be16b6aea 100644 --- a/spec/helpers/application_settings_helper_spec.rb +++ b/spec/helpers/application_settings_helper_spec.rb @@ -98,70 +98,6 @@ RSpec.describe ApplicationSettingsHelper do end end - describe '.self_monitoring_project_data' do - context 'when self-monitoring project does not exist' do - it 'returns create_self_monitoring_project_path' do - expect(helper.self_monitoring_project_data).to include( - 'create_self_monitoring_project_path' => - create_self_monitoring_project_admin_application_settings_path - ) - end - - it 'returns status_create_self_monitoring_project_path' do - expect(helper.self_monitoring_project_data).to include( - 'status_create_self_monitoring_project_path' => - status_create_self_monitoring_project_admin_application_settings_path - ) - end - - it 'returns delete_self_monitoring_project_path' do - expect(helper.self_monitoring_project_data).to include( - 'delete_self_monitoring_project_path' => - delete_self_monitoring_project_admin_application_settings_path - ) - end - - it 'returns status_delete_self_monitoring_project_path' do - expect(helper.self_monitoring_project_data).to include( - 'status_delete_self_monitoring_project_path' => - status_delete_self_monitoring_project_admin_application_settings_path - ) - end - - it 'returns self_monitoring_project_exists false' do - expect(helper.self_monitoring_project_data).to include( - 'self_monitoring_project_exists' => "false" - ) - end - - it 'returns nil for project full_path' do - expect(helper.self_monitoring_project_data).to include( - 'self_monitoring_project_full_path' => nil - ) - end - end - - context 'when self-monitoring project exists' do - let(:project) { build(:project) } - - before do - stub_application_setting(self_monitoring_project: project) - end - - it 'returns self_monitoring_project_exists true' do - expect(helper.self_monitoring_project_data).to include( - 'self_monitoring_project_exists' => "true" - ) - end - - it 'returns project full_path' do - expect(helper.self_monitoring_project_data).to include( - 'self_monitoring_project_full_path' => project.full_path - ) - end - end - end - describe '#storage_weights' do let(:application_setting) { build(:application_setting) } diff --git a/spec/helpers/jira_connect_helper_spec.rb b/spec/helpers/jira_connect_helper_spec.rb index 454e4bf3fda..b7c25320a0e 100644 --- a/spec/helpers/jira_connect_helper_spec.rb +++ b/spec/helpers/jira_connect_helper_spec.rb @@ -27,18 +27,12 @@ RSpec.describe JiraConnectHelper, feature_category: :integrations do it 'includes Jira Connect app attributes' do is_expected.to include( :groups_path, - :add_subscriptions_path, :subscriptions_path, - :users_path, :subscriptions, :gitlab_user_path ) end - it 'assigns users_path with value' do - expect(subject[:users_path]).to eq(jira_connect_users_path) - end - context 'with oauth_metadata' do let(:oauth_metadata) { helper.jira_connect_app_data([subscription], installation)[:oauth_metadata] } diff --git a/spec/lib/gitlab/metrics/dashboard/finder_spec.rb b/spec/lib/gitlab/metrics/dashboard/finder_spec.rb index f922eff2980..d3cb9760052 100644 --- a/spec/lib/gitlab/metrics/dashboard/finder_spec.rb +++ b/spec/lib/gitlab/metrics/dashboard/finder_spec.rb @@ -44,12 +44,6 @@ RSpec.describe Gitlab::Metrics::Dashboard::Finder, :use_clean_rails_memory_store it_behaves_like 'valid dashboard service response' end - context 'when the self-monitoring dashboard is specified' do - let(:dashboard_path) { self_monitoring_dashboard_path } - - it_behaves_like 'valid dashboard service response' - end - context 'when no dashboard is specified' do let(:service_call) { described_class.find(project, user, environment: environment) } @@ -180,36 +174,5 @@ RSpec.describe Gitlab::Metrics::Dashboard::Finder, :use_clean_rails_memory_store expect(all_dashboard_paths).to eq([project_dashboard2, k8s_pod_health_dashboard, project_dashboard1, system_dashboard]) end end - - context 'when the project is self-monitoring' do - let(:self_monitoring_dashboard) do - { - path: self_monitoring_dashboard_path, - display_name: 'Overview', - default: true, - system_dashboard: true, - out_of_the_box_dashboard: true - } - end - - let(:dashboard_path) { '.gitlab/dashboards/test.yml' } - let(:project) { project_with_dashboard(dashboard_path) } - - before do - stub_application_setting(self_monitoring_project_id: project.id) - end - - it 'includes self-monitoring and project dashboards' do - project_dashboard = { - path: dashboard_path, - display_name: 'test.yml', - default: false, - system_dashboard: false, - out_of_the_box_dashboard: false - } - - expect(all_dashboard_paths).to eq([self_monitoring_dashboard, project_dashboard]) - end - end end end diff --git a/spec/lib/gitlab/metrics/dashboard/service_selector_spec.rb b/spec/lib/gitlab/metrics/dashboard/service_selector_spec.rb index b41b51f53c3..343596af5cf 100644 --- a/spec/lib/gitlab/metrics/dashboard/service_selector_spec.rb +++ b/spec/lib/gitlab/metrics/dashboard/service_selector_spec.rb @@ -30,12 +30,6 @@ RSpec.describe Gitlab::Metrics::Dashboard::ServiceSelector do end end - context 'when the path is for the self-monitoring dashboard' do - let(:arguments) { { dashboard_path: self_monitoring_dashboard_path } } - - it { is_expected.to be Metrics::Dashboard::SelfMonitoringDashboardService } - end - context 'when the embedded flag is provided' do let(:arguments) { { embedded: true } } diff --git a/spec/requests/self_monitoring_project_spec.rb b/spec/requests/self_monitoring_project_spec.rb deleted file mode 100644 index ce4dd10a52d..00000000000 --- a/spec/requests/self_monitoring_project_spec.rb +++ /dev/null @@ -1,213 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe 'Self-Monitoring project requests', feature_category: :projects do - let(:admin) { create(:admin) } - - describe 'POST #create_self_monitoring_project' do - let(:worker_class) { SelfMonitoringProjectCreateWorker } - - subject { post create_self_monitoring_project_admin_application_settings_path } - - it_behaves_like 'not accessible to non-admin users' - - context 'with admin user', :enable_admin_mode do - before do - login_as(admin) - end - - context 'when the self-monitoring project is created' do - let(:status_api) { status_create_self_monitoring_project_admin_application_settings_path } - - it_behaves_like 'triggers async worker, returns sidekiq job_id with response accepted' - end - end - end - - describe 'GET #status_create_self_monitoring_project' do - let(:worker_class) { SelfMonitoringProjectCreateWorker } - let(:job_id) { 'job_id' } - - subject do - get status_create_self_monitoring_project_admin_application_settings_path, - params: { job_id: job_id } - end - - it_behaves_like 'not accessible to non-admin users' - - context 'with admin user', :enable_admin_mode do - before do - login_as(admin) - end - - context 'when the self-monitoring project is being created' do - it_behaves_like 'handles invalid job_id' - - context 'when job is in progress' do - before do - allow(worker_class).to receive(:in_progress?) - .with(job_id) - .and_return(true) - end - - it_behaves_like 'sets polling header and returns accepted' do - let(:in_progress_message) { 'Job to create self-monitoring project is in progress' } - end - end - - context 'when self-monitoring project and job do not exist' do - let(:job_id) { nil } - - it 'returns bad_request' do - create(:application_setting) - - subject - - aggregate_failures do - expect(response).to have_gitlab_http_status(:bad_request) - expect(json_response).to eq( - 'message' => 'Self-monitoring project does not exist. Please check logs ' \ - 'for any error messages' - ) - end - end - end - - context 'when self-monitoring project exists' do - let(:project) { create(:project) } - - before do - create(:application_setting, self_monitoring_project_id: project.id) - end - - it 'does not need job_id' do - get status_create_self_monitoring_project_admin_application_settings_path - - aggregate_failures do - expect(response).to have_gitlab_http_status(:success) - expect(json_response).to eq( - 'project_id' => project.id, - 'project_full_path' => project.full_path - ) - end - end - - it 'returns success with job_id' do - subject - - aggregate_failures do - expect(response).to have_gitlab_http_status(:success) - expect(json_response).to eq( - 'project_id' => project.id, - 'project_full_path' => project.full_path - ) - end - end - end - end - end - end - - describe 'DELETE #delete_self_monitoring_project' do - let(:worker_class) { SelfMonitoringProjectDeleteWorker } - - subject { delete delete_self_monitoring_project_admin_application_settings_path } - - it_behaves_like 'not accessible to non-admin users' - - context 'with admin user', :enable_admin_mode do - before do - login_as(admin) - end - - context 'when the self-monitoring project is deleted' do - let(:status_api) { status_delete_self_monitoring_project_admin_application_settings_path } - - it_behaves_like 'triggers async worker, returns sidekiq job_id with response accepted' - end - end - end - - describe 'GET #status_delete_self_monitoring_project' do - let(:worker_class) { SelfMonitoringProjectDeleteWorker } - let(:job_id) { 'job_id' } - - subject do - get status_delete_self_monitoring_project_admin_application_settings_path, - params: { job_id: job_id } - end - - it_behaves_like 'not accessible to non-admin users' - - context 'with admin user', :enable_admin_mode do - before do - login_as(admin) - end - - context 'when the self-monitoring project is being deleted' do - it_behaves_like 'handles invalid job_id' - - context 'when job is in progress' do - before do - allow(worker_class).to receive(:in_progress?) - .with(job_id) - .and_return(true) - - stub_application_setting(self_monitoring_project_id: 1) - end - - it_behaves_like 'sets polling header and returns accepted' do - let(:in_progress_message) { 'Job to delete self-monitoring project is in progress' } - end - end - - context 'when self-monitoring project exists and job does not exist' do - before do - create(:application_setting, self_monitoring_project_id: create(:project).id) - end - - it 'returns bad_request' do - subject - - aggregate_failures do - expect(response).to have_gitlab_http_status(:bad_request) - expect(json_response).to eq( - 'message' => 'Self-monitoring project was not deleted. Please check logs ' \ - 'for any error messages' - ) - end - end - end - - context 'when self-monitoring project does not exist' do - before do - create(:application_setting) - end - - it 'does not need job_id' do - get status_delete_self_monitoring_project_admin_application_settings_path - - aggregate_failures do - expect(response).to have_gitlab_http_status(:success) - expect(json_response).to eq( - 'message' => 'Self-monitoring project has been successfully deleted' - ) - end - end - - it 'returns success with job_id' do - subject - - aggregate_failures do - expect(response).to have_gitlab_http_status(:success) - expect(json_response).to eq( - 'message' => 'Self-monitoring project has been successfully deleted' - ) - end - end - end - end - end - end -end diff --git a/spec/services/metrics/dashboard/clone_dashboard_service_spec.rb b/spec/services/metrics/dashboard/clone_dashboard_service_spec.rb index 40ec37c393d..bb11b905a7c 100644 --- a/spec/services/metrics/dashboard/clone_dashboard_service_spec.rb +++ b/spec/services/metrics/dashboard/clone_dashboard_service_spec.rb @@ -92,10 +92,6 @@ RSpec.describe Metrics::Dashboard::CloneDashboardService, :use_clean_rails_memor ::Gitlab::Metrics::Dashboard::Stages::CommonMetricsInserter ] - it_behaves_like 'valid dashboard cloning process', - ::Metrics::Dashboard::SelfMonitoringDashboardService::DASHBOARD_PATH, - [::Gitlab::Metrics::Dashboard::Stages::CustomMetricsInserter] - context 'selected branch already exists' do let(:branch) { 'existing_branch' } diff --git a/spec/services/metrics/dashboard/self_monitoring_dashboard_service_spec.rb b/spec/services/metrics/dashboard/self_monitoring_dashboard_service_spec.rb index 930789ed701..bc7af95957b 100644 --- a/spec/services/metrics/dashboard/self_monitoring_dashboard_service_spec.rb +++ b/spec/services/metrics/dashboard/self_monitoring_dashboard_service_spec.rb @@ -67,12 +67,6 @@ RSpec.describe Metrics::Dashboard::SelfMonitoringDashboardService, :use_clean_ra it { is_expected.to be_truthy } end - context 'with dashboard_path' do - let(:params) { { dashboard_path: self_monitoring_dashboard_path } } - - it { is_expected.to be_truthy } - end - context 'with a different dashboard selected' do let(:dashboard_path) { '.gitlab/dashboards/test.yml' } let(:params) { { dashboard_path: dashboard_path, environment: environment } } diff --git a/spec/support/helpers/metrics_dashboard_helpers.rb b/spec/support/helpers/metrics_dashboard_helpers.rb index a384e44f428..417baeda33a 100644 --- a/spec/support/helpers/metrics_dashboard_helpers.rb +++ b/spec/support/helpers/metrics_dashboard_helpers.rb @@ -49,8 +49,4 @@ module MetricsDashboardHelpers def business_metric_title Enums::PrometheusMetric.group_details[:business][:group_title] end - - def self_monitoring_dashboard_path - Metrics::Dashboard::SelfMonitoringDashboardService::DASHBOARD_PATH - end end diff --git a/spec/tooling/danger/product_intelligence_spec.rb b/spec/tooling/danger/product_intelligence_spec.rb index c4cd0e5bfb6..bc6b9debfe0 100644 --- a/spec/tooling/danger/product_intelligence_spec.rb +++ b/spec/tooling/danger/product_intelligence_spec.rb @@ -32,10 +32,12 @@ RSpec.describe Tooling::Danger::ProductIntelligence do let(:approved_label) { 'product intelligence::approved' } let(:changed_files) { ['metrics/counts_7d/test_metric.yml'] } let(:changed_lines) { ['+tier: ee'] } + let(:fake_changes) { instance_double(Gitlab::Dangerfiles::Changes, files: changed_files) } before do + allow(fake_changes).to receive(:by_category).with(:product_intelligence).and_return(fake_changes) + allow(fake_helper).to receive(:changes).and_return(fake_changes) allow(fake_helper).to receive(:all_changed_files).and_return(changed_files) - allow(fake_helper).to receive(:changes_by_category).and_return(product_intelligence: changed_files, database: ['other_files.yml']) allow(fake_helper).to receive(:markdown_list).with(changed_files).and_return(markdown_formatted_list) end @@ -61,6 +63,15 @@ RSpec.describe Tooling::Danger::ProductIntelligence do expect(labels_to_add).to match_array [previous_label_to_add, review_pending_label] end + + it 'receives all the changed files by calling the correct helper method', :aggregate_failures do + expect(fake_helper).not_to receive(:changes_by_category) + expect(fake_helper).to receive(:changes) + expect(fake_changes).to receive(:by_category).with(:product_intelligence) + expect(fake_changes).to receive(:files) + + subject + end end context 'with growth experiment label' do diff --git a/tooling/danger/product_intelligence.rb b/tooling/danger/product_intelligence.rb index d25f966504f..00dc31b9bb9 100644 --- a/tooling/danger/product_intelligence.rb +++ b/tooling/danger/product_intelligence.rb @@ -33,8 +33,8 @@ module Tooling ].freeze def check! - # exit if not matching files or if no product intelligence labels - product_intelligence_paths_to_review = helper.changes_by_category[:product_intelligence] + product_intelligence_paths_to_review = helper.changes.by_category(:product_intelligence).files + labels_to_add = missing_labels return if product_intelligence_paths_to_review.empty? || skip_review? |
