diff options
185 files changed, 1347 insertions, 296 deletions
diff --git a/.rubocop_todo/layout/line_length.yml b/.rubocop_todo/layout/line_length.yml index bd7bf28a1f3..01c83d7ac5d 100644 --- a/.rubocop_todo/layout/line_length.yml +++ b/.rubocop_todo/layout/line_length.yml @@ -5280,7 +5280,6 @@ Layout/LineLength: - 'spec/models/ci/instance_variable_spec.rb' - 'spec/models/ci/job_artifact_spec.rb' - 'spec/models/ci/job_token/scope_spec.rb' - - 'spec/models/ci/namespace_mirror_spec.rb' - 'spec/models/ci/pipeline_schedule_spec.rb' - 'spec/models/ci/pipeline_spec.rb' - 'spec/models/ci/processable_spec.rb' diff --git a/app/assets/javascripts/jira_connect/subscriptions/api.js b/app/assets/javascripts/jira_connect/subscriptions/api.js index ffe5642fc62..8b32a67c23b 100644 --- a/app/assets/javascripts/jira_connect/subscriptions/api.js +++ b/app/assets/javascripts/jira_connect/subscriptions/api.js @@ -1,13 +1,21 @@ import axios from 'axios'; import { buildApiUrl } from '~/api/api_utils'; +import { GITLAB_COM_BASE_PATH } from '~/jira_connect/subscriptions/constants'; import { getJwt } from './utils'; const CURRENT_USER_PATH = '/api/:version/user'; const JIRA_CONNECT_SUBSCRIPTIONS_PATH = '/api/:version/integrations/jira_connect/subscriptions'; +const JIRA_CONNECT_INSTALLATIONS_PATH = '/-/jira_connect/installations'; +const JIRA_CONNECT_OAUTH_APPLICATION_ID_PATH = '/-/jira_connect/oauth_application_id'; +// This export is only used for testing purposes export const axiosInstance = axios.create(); +export const setApiBaseURL = (baseURL = null) => { + axiosInstance.defaults.baseURL = baseURL; +}; + export const addSubscription = async (addPath, namespace) => { const jwt = await getJwt(); @@ -68,3 +76,22 @@ export const addJiraConnectSubscription = (namespacePath, { jwt, accessToken }) }, ); }; + +export const updateInstallation = async (instanceUrl) => { + const jwt = await getJwt(); + + return axiosInstance.put(JIRA_CONNECT_INSTALLATIONS_PATH, { + jwt, + installation: { + instance_url: instanceUrl === GITLAB_COM_BASE_PATH ? null : instanceUrl, + }, + }); +}; + +export const fetchOAuthApplicationId = () => { + return axiosInstance.get(JIRA_CONNECT_OAUTH_APPLICATION_ID_PATH); +}; + +export const fetchOAuthToken = (oauthTokenURL, data = {}) => { + return axiosInstance.post(oauthTokenURL, data); +}; diff --git a/app/assets/javascripts/jira_connect/subscriptions/components/compatibility_alert.vue b/app/assets/javascripts/jira_connect/subscriptions/components/compatibility_alert.vue index c5b56535247..9b50681515e 100644 --- a/app/assets/javascripts/jira_connect/subscriptions/components/compatibility_alert.vue +++ b/app/assets/javascripts/jira_connect/subscriptions/components/compatibility_alert.vue @@ -3,6 +3,7 @@ import { GlAlert, GlSprintf, GlLink } from '@gitlab/ui'; import { s__ } from '~/locale'; import { helpPagePath } from '~/helpers/help_page_helper'; import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue'; +import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; const COMPATIBILITY_ALERT_STATE_KEY = 'compatibility_alert_dismissed'; @@ -14,6 +15,7 @@ export default { GlLink, LocalStorageSync, }, + mixins: [glFeatureFlagMixin()], data() { return { alertDismissed: false, @@ -23,6 +25,14 @@ export default { shouldShowAlert() { return !this.alertDismissed; }, + isOauthSelfManagedEnabled() { + return this.glFeatures.jiraConnectOauth && this.glFeatures.jiraConnectOauthSelfManaged; + }, + alertBody() { + return this.isOauthSelfManagedEnabled + ? this.$options.i18n.body + : this.$options.i18n.bodyDotCom; + }, }, methods: { dismissAlert() { @@ -32,6 +42,9 @@ export default { i18n: { title: s__('Integrations|Known limitations'), body: s__( + 'Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}.', + ), + bodyDotCom: s__( 'Integrations|This integration only works with GitLab.com. Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}.', ), }, @@ -50,7 +63,7 @@ export default { :title="$options.i18n.title" @dismiss="dismissAlert" > - <gl-sprintf :message="$options.i18n.body"> + <gl-sprintf :message="alertBody"> <template #link="{ content }"> <gl-link :href="$options.DOCS_LINK_URL" target="_blank">{{ content }}</gl-link> </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 d2528e61f21..8df906dd292 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 @@ -1,18 +1,23 @@ <script> import { mapActions, mapMutations } from 'vuex'; import { GlButton } from '@gitlab/ui'; -import axios from '~/lib/utils/axios_utils'; import { sprintf } from '~/locale'; + import { I18N_DEFAULT_SIGN_IN_BUTTON_TEXT, I18N_CUSTOM_SIGN_IN_BUTTON_TEXT, + I18N_OAUTH_APPLICATION_ID_ERROR_MESSAGE, + I18N_OAUTH_FAILED_TITLE, + I18N_OAUTH_FAILED_MESSAGE, + OAUTH_SELF_MANAGED_DOC_LINK, OAUTH_WINDOW_OPTIONS, PKCE_CODE_CHALLENGE_DIGEST_ALGORITHM, } from '~/jira_connect/subscriptions/constants'; +import { fetchOAuthApplicationId, fetchOAuthToken } from '~/jira_connect/subscriptions/api'; import { setUrlParams } from '~/lib/utils/url_utility'; import AccessorUtilities from '~/lib/utils/accessor'; import { createCodeVerifier, createCodeChallenge } from '../pkce'; -import { SET_ACCESS_TOKEN } from '../store/mutation_types'; +import { SET_ACCESS_TOKEN, SET_ALERT } from '../store/mutation_types'; export default { components: { @@ -30,6 +35,7 @@ export default { return { loading: false, codeVerifier: null, + clientId: null, canUseCrypto: AccessorUtilities.canUseCrypto(), }; }, @@ -52,30 +58,72 @@ export default { ...mapActions(['loadCurrentUser']), ...mapMutations({ setAccessToken: SET_ACCESS_TOKEN, + setAlert: SET_ALERT, }), - async startOAuthFlow() { - this.loading = true; - + async fetchOauthClientId() { + const { + data: { application_id: clientId }, + } = await fetchOAuthApplicationId(); + return clientId; + }, + async getOauthAuthorizeURL() { // Generate state necessary for PKCE OAuth flow this.codeVerifier = createCodeVerifier(); const codeChallenge = await createCodeChallenge(this.codeVerifier); + try { + this.clientId = this.gitlabBasePath + ? await this.fetchOauthClientId() + : this.oauthMetadata?.oauth_token_payload?.client_id; + } catch { + throw new Error(I18N_OAUTH_APPLICATION_ID_ERROR_MESSAGE); + } // Build the initial OAuth authorization URL const { oauth_authorize_url: oauthAuthorizeURL } = this.oauthMetadata; - - const oauthAuthorizeURLWithChallenge = setUrlParams( - { - code_challenge: codeChallenge, - code_challenge_method: PKCE_CODE_CHALLENGE_DIGEST_ALGORITHM.short, - }, - oauthAuthorizeURL, + const oauthAuthorizeURLWithChallenge = new URL( + setUrlParams( + { + code_challenge: codeChallenge, + code_challenge_method: PKCE_CODE_CHALLENGE_DIGEST_ALGORITHM.short, + client_id: this.clientId, + }, + oauthAuthorizeURL, + ), ); - window.open( - oauthAuthorizeURLWithChallenge, - I18N_DEFAULT_SIGN_IN_BUTTON_TEXT, - OAUTH_WINDOW_OPTIONS, - ); + // Rebase URL on the specified GitLab base path (if specified). + if (this.gitlabBasePath) { + const gitlabBasePathURL = new URL(this.gitlabBasePath); + oauthAuthorizeURLWithChallenge.hostname = gitlabBasePathURL.hostname; + oauthAuthorizeURLWithChallenge.pathname = `${ + gitlabBasePathURL.pathname === '/' ? '' : gitlabBasePathURL.pathname + }${oauthAuthorizeURLWithChallenge.pathname}`; + } + + return oauthAuthorizeURLWithChallenge.toString(); + }, + async startOAuthFlow() { + try { + this.loading = true; + const oauthAuthorizeURL = await this.getOauthAuthorizeURL(); + + window.open(oauthAuthorizeURL, I18N_DEFAULT_SIGN_IN_BUTTON_TEXT, OAUTH_WINDOW_OPTIONS); + } catch (e) { + if (e.message) { + this.setAlert({ + message: e.message, + variant: 'danger', + }); + } else { + this.setAlert({ + linkUrl: OAUTH_SELF_MANAGED_DOC_LINK, + title: I18N_OAUTH_FAILED_TITLE, + message: this.gitlabBasePath ? I18N_OAUTH_FAILED_MESSAGE : '', + variant: 'danger', + }); + } + this.loading = false; + } }, async handleWindowMessage(event) { if (window.origin !== event.origin) { @@ -113,10 +161,11 @@ export default { oauth_token_payload: oauthTokenPayload, oauth_token_url: oauthTokenURL, } = this.oauthMetadata; - const { data } = await axios.post(oauthTokenURL, { + const { data } = await fetchOAuthToken(oauthTokenURL, { ...oauthTokenPayload, code, code_verifier: this.codeVerifier, + client_id: this.clientId, }); return data.access_token; diff --git a/app/assets/javascripts/jira_connect/subscriptions/constants.js b/app/assets/javascripts/jira_connect/subscriptions/constants.js index 2a7d96f24eb..fc365746b54 100644 --- a/app/assets/javascripts/jira_connect/subscriptions/constants.js +++ b/app/assets/javascripts/jira_connect/subscriptions/constants.js @@ -20,13 +20,26 @@ export const I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_TITLE = s__( export const I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_MESSAGE = s__( 'Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}', ); -export const INTEGRATIONS_DOC_LINK = helpPagePath('integration/jira_development_panel', { - anchor: 'use-the-integration', -}); - export const I18N_ADD_SUBSCRIPTIONS_ERROR_MESSAGE = s__( 'Integrations|Failed to link namespace. Please try again.', ); +export const I18N_UPDATE_INSTALLATION_ERROR_MESSAGE = s__( + 'Integrations|Failed to update GitLab version. Please try again.', +); +export const I18N_OAUTH_APPLICATION_ID_ERROR_MESSAGE = s__( + 'Integrations|Failed to load Jira Connect Application ID. Please try again.', +); +export const I18N_OAUTH_FAILED_TITLE = s__('Integrations|Failed to sign in to GitLab.'); +export const I18N_OAUTH_FAILED_MESSAGE = s__( + 'Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}.', +); + +export const INTEGRATIONS_DOC_LINK = helpPagePath('integration/jira/development_panel', { + anchor: 'use-the-integration', +}); +export const OAUTH_SELF_MANAGED_DOC_LINK = helpPagePath('integration/jira/connect-app', { + anchor: 'install-the-gitlabcom-for-jira-cloud-app-for-self-managed-instances', +}); export const GITLAB_COM_BASE_PATH = 'https://gitlab.com'; diff --git a/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/index.vue b/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/index.vue index 64cd7793925..5ff75e19425 100644 --- a/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/index.vue +++ b/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/index.vue @@ -1,7 +1,13 @@ <script> +import { mapMutations } from 'vuex'; import { GlButton } from '@gitlab/ui'; import { s__ } from '~/locale'; +import { reloadPage, persistBaseUrl, retrieveBaseUrl } from '~/jira_connect/subscriptions/utils'; +import { updateInstallation, setApiBaseURL } from '~/jira_connect/subscriptions/api'; +import { I18N_UPDATE_INSTALLATION_ERROR_MESSAGE } from '~/jira_connect/subscriptions/constants'; +import { SET_ALERT } from '~/jira_connect/subscriptions/store/mutation_types'; + import SignInOauthButton from '../../../components/sign_in_oauth_button.vue'; import VersionSelectForm from './version_select_form.vue'; @@ -15,6 +21,7 @@ export default { data() { return { gitlabBasePath: null, + loadingVersionSelect: false, }; }, computed: { @@ -27,12 +34,32 @@ export default { : this.$options.i18n.versionSelectSubtitle; }, }, + mounted() { + this.gitlabBasePath = retrieveBaseUrl(); + setApiBaseURL(this.gitlabBasePath); + }, methods: { + ...mapMutations({ + setAlert: SET_ALERT, + }), resetGitlabBasePath() { this.gitlabBasePath = null; + setApiBaseURL(); }, onVersionSelect(gitlabBasePath) { - this.gitlabBasePath = gitlabBasePath; + this.loadingVersionSelect = true; + updateInstallation(gitlabBasePath) + .then(() => { + persistBaseUrl(gitlabBasePath); + reloadPage(); + }) + .catch(() => { + this.setAlert({ + message: I18N_UPDATE_INSTALLATION_ERROR_MESSAGE, + variant: 'danger', + }); + this.loadingVersionSelect = false; + }); }, onSignInError() { this.$emit('error'); @@ -54,7 +81,12 @@ export default { <p data-testid="subtitle">{{ subtitle }}</p> </div> - <version-select-form v-if="!hasSelectedVersion" class="gl-mt-7" @submit="onVersionSelect" /> + <version-select-form + v-if="!hasSelectedVersion" + class="gl-mt-7" + :loading="loadingVersionSelect" + @submit="onVersionSelect" + /> <div v-else class="gl-text-center"> <sign-in-oauth-button diff --git a/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/version_select_form.vue b/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/version_select_form.vue index 9b0bc476537..6b32225ed11 100644 --- a/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/version_select_form.vue +++ b/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/version_select_form.vue @@ -28,6 +28,13 @@ export default { GlFormRadio, GlButton, }, + props: { + loading: { + type: Boolean, + required: false, + default: false, + }, + }, data() { return { selected: DEFAULT_RADIO_OPTION, @@ -83,7 +90,7 @@ export default { </gl-form-group> <div class="gl-display-flex gl-justify-content-end"> - <gl-button variant="confirm" type="submit">{{ __('Save') }}</gl-button> + <gl-button variant="confirm" type="submit" :loading="loading">{{ __('Save') }}</gl-button> </div> </gl-form> </template> diff --git a/app/assets/javascripts/members/constants.js b/app/assets/javascripts/members/constants.js index 93d113d1afe..3135ec602be 100644 --- a/app/assets/javascripts/members/constants.js +++ b/app/assets/javascripts/members/constants.js @@ -196,3 +196,8 @@ export const MEMBER_ACCESS_LEVEL_PROPERTY_NAME = 'access_level'; export const GROUP_LINK_BASE_PROPERTY_NAME = 'group_link'; export const GROUP_LINK_ACCESS_LEVEL_PROPERTY_NAME = 'group_access'; + +export const I18N_USER_YOU = __("It's you"); +export const I18N_USER_BLOCKED = __('Blocked'); +export const I18N_USER_BOT = __('Bot'); +export const I188N_USER_2FA = __('2FA'); diff --git a/app/assets/javascripts/members/utils.js b/app/assets/javascripts/members/utils.js index 7ec083646e9..0da44b7d468 100644 --- a/app/assets/javascripts/members/utils.js +++ b/app/assets/javascripts/members/utils.js @@ -1,28 +1,36 @@ import { isUndefined } from 'lodash'; import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; import { getParameterByName, setUrlParams } from '~/lib/utils/url_utility'; -import { __ } from '~/locale'; import { FIELDS, DEFAULT_SORT, GROUP_LINK_BASE_PROPERTY_NAME, GROUP_LINK_ACCESS_LEVEL_PROPERTY_NAME, + I18N_USER_YOU, + I18N_USER_BLOCKED, + I18N_USER_BOT, + I188N_USER_2FA, } from './constants'; export const generateBadges = ({ member, isCurrentUser, canManageMembers }) => [ { show: isCurrentUser, - text: __("It's you"), + text: I18N_USER_YOU, variant: 'success', }, { show: member.user?.blocked, - text: __('Blocked'), + text: I18N_USER_BLOCKED, variant: 'danger', }, { + show: member.user?.isBot, + text: I18N_USER_BOT, + variant: 'muted', + }, + { show: member.user?.twoFactorEnabled && (canManageMembers || isCurrentUser), - text: __('2FA'), + text: I188N_USER_2FA, variant: 'info', }, ]; diff --git a/app/assets/javascripts/packages_and_registries/harbor_registry/components/list/harbor_list_header.vue b/app/assets/javascripts/packages_and_registries/harbor_registry/components/list/harbor_list_header.vue index f9aefeeb46f..db66ebef937 100644 --- a/app/assets/javascripts/packages_and_registries/harbor_registry/components/list/harbor_list_header.vue +++ b/app/assets/javascripts/packages_and_registries/harbor_registry/components/list/harbor_list_header.vue @@ -5,6 +5,7 @@ import { HARBOR_REGISTRY_TITLE, LIST_INTRO_TEXT, imagesCountInfoText, + HARBOR_REGISTRY_HELP_PAGE_PATH, } from '~/packages_and_registries/harbor_registry/constants'; import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue'; @@ -20,11 +21,6 @@ export default { default: 0, required: false, }, - helpPagePath: { - type: String, - default: '', - required: false, - }, metadataLoading: { type: Boolean, required: false, @@ -40,7 +36,7 @@ export default { return sprintf(pluralisedString, { count: this.imagesCount }); }, infoMessages() { - return [{ text: LIST_INTRO_TEXT, link: this.helpPagePath }]; + return [{ text: LIST_INTRO_TEXT, link: HARBOR_REGISTRY_HELP_PAGE_PATH }]; }, }, }; diff --git a/app/assets/javascripts/packages_and_registries/harbor_registry/constants/common.js b/app/assets/javascripts/packages_and_registries/harbor_registry/constants/common.js index 89866320215..7f3c3da02b0 100644 --- a/app/assets/javascripts/packages_and_registries/harbor_registry/constants/common.js +++ b/app/assets/javascripts/packages_and_registries/harbor_registry/constants/common.js @@ -1,4 +1,5 @@ import { s__, __ } from '~/locale'; +import { helpPagePath } from '~/helpers/help_page_helper'; export const ROOT_IMAGE_TEXT = s__('HarborRegistry|Root image'); export const NAME_SORT_FIELD = { orderBy: 'NAME', label: __('Name') }; @@ -17,3 +18,7 @@ export const SORT_FIELD_MAPPING = { }; export const DEFAULT_PER_PAGE = 10; + +export const HARBOR_REGISTRY_HELP_PAGE_PATH = helpPagePath( + 'user/packages/harbor_container_registry/index', +); diff --git a/app/assets/javascripts/packages_and_registries/harbor_registry/constants/list.js b/app/assets/javascripts/packages_and_registries/harbor_registry/constants/list.js index 6a51d14d570..33950993125 100644 --- a/app/assets/javascripts/packages_and_registries/harbor_registry/constants/list.js +++ b/app/assets/javascripts/packages_and_registries/harbor_registry/constants/list.js @@ -7,7 +7,7 @@ export const HARBOR_REGISTRY_TITLE = s__('HarborRegistry|Harbor Registry'); export const CONNECTION_ERROR_TITLE = s__('HarborRegistry|Harbor connection error'); export const CONNECTION_ERROR_MESSAGE = s__( - `HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}.`, + `HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}.`, ); export const FETCH_IMAGES_LIST_ERROR_MESSAGE = s__( diff --git a/app/assets/javascripts/packages_and_registries/harbor_registry/index.js b/app/assets/javascripts/packages_and_registries/harbor_registry/index.js index 70238e43ad6..6185e4c7bc6 100644 --- a/app/assets/javascripts/packages_and_registries/harbor_registry/index.js +++ b/app/assets/javascripts/packages_and_registries/harbor_registry/index.js @@ -70,7 +70,6 @@ export default (id) => { projectName, containersErrorImage, noContainersImage, - helpPagePath: '', }; }, render(createElement) { diff --git a/app/assets/javascripts/packages_and_registries/harbor_registry/pages/list.vue b/app/assets/javascripts/packages_and_registries/harbor_registry/pages/list.vue index b9ec625171e..931a99649cb 100644 --- a/app/assets/javascripts/packages_and_registries/harbor_registry/pages/list.vue +++ b/app/assets/javascripts/packages_and_registries/harbor_registry/pages/list.vue @@ -23,6 +23,7 @@ import { FETCH_IMAGES_LIST_ERROR_MESSAGE, EMPTY_IMAGES_TITLE, EMPTY_IMAGES_MESSAGE, + HARBOR_REGISTRY_HELP_PAGE_PATH, } from '~/packages_and_registries/harbor_registry/constants'; import Tracking from '~/tracking'; import { getHarborRepositoriesList } from '~/rest_api'; @@ -52,7 +53,6 @@ export default { 'connectionError', 'invalidPathError', 'containersErrorImage', - 'helpPagePath', 'noContainersImage', ], loader: { @@ -65,6 +65,7 @@ export default { connectionErrorMessage: CONNECTION_ERROR_MESSAGE, }, searchConfig: SORT_FIELDS, + helpPagePath: HARBOR_REGISTRY_HELP_PAGE_PATH, data() { return { images: [], @@ -168,7 +169,7 @@ export default { <p> <gl-sprintf :message="$options.i18n.connectionErrorMessage"> <template #docLink="{ content }"> - <gl-link :href="`${helpPagePath}#docker-connection-error`" target="_blank"> + <gl-link :href="$options.helpPagePath" target="_blank"> {{ content }} </gl-link> </template> @@ -177,11 +178,7 @@ export default { </template> </gl-empty-state> <template v-else> - <harbor-list-header - :metadata-loading="isLoading" - :images-count="totalCount" - :help-page-path="helpPagePath" - > + <harbor-list-header :metadata-loading="isLoading" :images-count="totalCount"> <template #commands> <cli-commands v-if="showCommands" diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue b/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue index 861ee3729ca..300e2a672cb 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue @@ -319,7 +319,7 @@ export default { :status="statusIconName" :is-loading="isLoadingSummary" :class="{ 'gl-cursor-pointer': isCollapsible }" - class="gl-p-5 gl--flex-center" + class="gl-p-5" @mousedown="onRowMouseDown" @mouseup="onRowMouseUp" > diff --git a/app/assets/stylesheets/page_bundles/merge_requests.scss b/app/assets/stylesheets/page_bundles/merge_requests.scss index 57267e061b4..463c8f74342 100644 --- a/app/assets/stylesheets/page_bundles/merge_requests.scss +++ b/app/assets/stylesheets/page_bundles/merge_requests.scss @@ -200,12 +200,8 @@ $tabs-holder-z-index: 250; background-color: var(--gray-50, $gray-50); } -.mr-conflict-loader { - max-width: 334px; - - > svg { - vertical-align: middle; - } +.mr-widget-body-loading svg { + vertical-align: middle; } .mr-info-list { diff --git a/app/finders/merge_requests_finder.rb b/app/finders/merge_requests_finder.rb index 81e4ab7014d..ffa912afd1e 100644 --- a/app/finders/merge_requests_finder.rb +++ b/app/finders/merge_requests_finder.rb @@ -30,6 +30,8 @@ # updated_before: datetime # class MergeRequestsFinder < IssuableFinder + extend ::Gitlab::Utils::Override + include MergedAtFilter def self.scalar_params @@ -82,6 +84,16 @@ class MergeRequestsFinder < IssuableFinder private + override :sort + def sort(items) + items = super(items) + + return items unless use_grouping_columns? + + grouping_columns = klass.grouping_columns(params[:sort]) + items.group(grouping_columns) # rubocop:disable CodeReuse/ActiveRecord + end + def by_commit(items) return items unless params[:commit_sha].presence @@ -224,6 +236,12 @@ class MergeRequestsFinder < IssuableFinder rescue Date::Error nil end + + def use_grouping_columns? + return false unless params[:sort].present? + + params[:approved_by_usernames].present? || params[:approved_by_ids].present? + end end MergeRequestsFinder.prepend_mod_with('MergeRequestsFinder') diff --git a/app/models/ci/namespace_mirror.rb b/app/models/ci/namespace_mirror.rb index e8f08db597f..5ea51fbe0a7 100644 --- a/app/models/ci/namespace_mirror.rb +++ b/app/models/ci/namespace_mirror.rb @@ -43,20 +43,6 @@ module Ci upsert({ namespace_id: event.namespace_id, traversal_ids: traversal_ids }, unique_by: :namespace_id) - - # It won't be necessary once we remove `sync_traversal_ids`. - # More info: https://gitlab.com/gitlab-org/gitlab/-/issues/347541 - sync_children_namespaces!(event.namespace_id, traversal_ids) - end - - private - - def sync_children_namespaces!(namespace_id, traversal_ids) - by_group_and_descendants(namespace_id) - .where.not(namespace_id: namespace_id) - .update_all( - "traversal_ids = ARRAY[#{sanitize_sql(traversal_ids.join(','))}]::int[] || traversal_ids[array_position(traversal_ids, #{sanitize_sql(namespace_id)}) + 1:]" - ) end end end diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index eb17770ab62..3a3e5f65c9b 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -1083,11 +1083,15 @@ module Ci latest_test_report_builds.failed.limit(limit) end + def has_reports?(reports_scope) + latest_report_builds(reports_scope).exists? + end + def complete_and_has_reports?(reports_scope) if Feature.enabled?(:mr_show_reports_immediately, project, type: :development) latest_report_builds(reports_scope).exists? else - complete? && latest_report_builds(reports_scope).exists? + complete? && has_reports?(reports_scope) end end @@ -1323,7 +1327,7 @@ module Ci def has_test_reports? strong_memoize(:has_test_reports) do - complete_and_has_reports?(::Ci::JobArtifact.of_report_type(:test)) + has_reports?(::Ci::JobArtifact.of_report_type(:test)) end end diff --git a/app/models/namespace.rb b/app/models/namespace.rb index 17d4c6d27e6..4c0aa3e3cea 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -131,7 +131,6 @@ class Namespace < ApplicationRecord delegate :show_diff_preview_in_email, :show_diff_preview_in_email?, :show_diff_preview_in_email=, to: :namespace_settings - after_save :schedule_sync_event_worker, if: -> { saved_change_to_id? || saved_change_to_parent_id? } after_save :reload_namespace_details after_commit :refresh_access_of_projects_invited_groups, on: :update, if: -> { previous_changes.key?('share_with_group_lock') } @@ -140,6 +139,7 @@ class Namespace < ApplicationRecord before_update :sync_share_with_group_lock_with_parent, if: :parent_changed? after_update :force_share_with_group_lock_on_descendants, if: -> { saved_change_to_share_with_group_lock? && share_with_group_lock? } after_update :expire_first_auto_devops_config_cache, if: -> { saved_change_to_auto_devops_enabled? } + after_sync_traversal_ids :schedule_sync_event_worker # custom callback defined in Namespaces::Traversal::Linear # Legacy Storage specific hooks diff --git a/app/models/namespaces/traversal/linear.rb b/app/models/namespaces/traversal/linear.rb index 687fa6a5334..16a9c20dfdc 100644 --- a/app/models/namespaces/traversal/linear.rb +++ b/app/models/namespaces/traversal/linear.rb @@ -47,6 +47,8 @@ module Namespaces # This uses rails internal before_commit API to sync traversal_ids on namespace create, right before transaction is committed. # This helps reduce the time during which the root namespace record is locked to ensure updated traversal_ids are valid before_commit :sync_traversal_ids, on: [:create] + + define_model_callbacks :sync_traversal_ids end class_methods do @@ -208,10 +210,12 @@ module Namespaces # # NOTE: self.traversal_ids will be stale. Reload for a fresh record. def sync_traversal_ids - # Clear any previously memoized root_ancestor as our ancestors have changed. - clear_memoization(:root_ancestor) + run_callbacks :sync_traversal_ids do + # Clear any previously memoized root_ancestor as our ancestors have changed. + clear_memoization(:root_ancestor) - Namespace::TraversalHierarchy.for_namespace(self).sync_traversal_ids! + Namespace::TraversalHierarchy.for_namespace(self).sync_traversal_ids! + end end # Lock the root of the hierarchy we just left, and lock the root of the hierarchy diff --git a/app/models/note.rb b/app/models/note.rb index 1715f7cdc3b..daac489757b 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -164,6 +164,9 @@ class Note < ApplicationRecord scope :like_note_or_capitalized_note, ->(text) { where('(note LIKE ? OR note LIKE ?)', text, text.capitalize) } before_validation :nullify_blank_type, :nullify_blank_line_code + # Syncs `confidential` with `internal` as we rename the column. + # https://gitlab.com/gitlab-org/gitlab/-/issues/367923 + before_create :set_internal_flag after_save :keep_around_commit, if: :for_project_noteable?, unless: -> { importing? || skip_keep_around_commits } after_save :expire_etag_cache, unless: :importing? after_save :touch_noteable, unless: :importing? @@ -813,6 +816,10 @@ class Note < ApplicationRecord def noteable_can_have_confidential_note? for_issue? end + + def set_internal_flag + self.internal = confidential if confidential + end end Note.prepend_mod_with('Note') diff --git a/app/serializers/member_user_entity.rb b/app/serializers/member_user_entity.rb index 6a01c5bb297..73cb9a4a798 100644 --- a/app/serializers/member_user_entity.rb +++ b/app/serializers/member_user_entity.rb @@ -16,6 +16,10 @@ class MemberUserEntity < UserEntity user.blocked? end + expose :is_bot do |user| + user.bot? + end + expose :two_factor_enabled, if: -> (user) { current_user_can_manage_members? || current_user?(user) } do |user| user.two_factor_enabled? end diff --git a/app/views/layouts/header/_current_user_dropdown.html.haml b/app/views/layouts/header/_current_user_dropdown.html.haml index 353f07c07c5..00e7a0567da 100644 --- a/app/views/layouts/header/_current_user_dropdown.html.haml +++ b/app/views/layouts/header/_current_user_dropdown.html.haml @@ -37,7 +37,7 @@ %li.d-md-none = render 'shared/help_dropdown_forum_link' %li.d-md-none - = link_to _("Submit feedback"), "https://about.gitlab.com/submit-feedback" + = link_to _("Submit feedback"), Gitlab::Utils.append_path(promo_url, "submit-feedback") - if current_user_menu?(:help) || current_user_menu?(:settings) || current_user_menu?(:profile) %li.d-md-none = render 'shared/user_dropdown_contributing_link' diff --git a/app/views/projects/default_branch/_show.html.haml b/app/views/projects/default_branch/_show.html.haml index b1fb9c70a54..eba0f336f80 100644 --- a/app/views/projects/default_branch/_show.html.haml +++ b/app/views/projects/default_branch/_show.html.haml @@ -16,7 +16,7 @@ = _('A default branch cannot be chosen for an empty project.') - else .form-group - = f.label :default_branch, "Default branch", class: 'label-bold' + = f.label :default_branch, _("Default branch"), class: 'label-bold' = f.select(:default_branch, @project.repository.branch_names, {}, {class: 'select2 select-wide', data: { qa_selector: 'default_branch_dropdown' }}) .form-group diff --git a/app/workers/gitlab/jira_import/import_issue_worker.rb b/app/workers/gitlab/jira_import/import_issue_worker.rb index 3824cc1f3ef..eabe988dfc2 100644 --- a/app/workers/gitlab/jira_import/import_issue_worker.rb +++ b/app/workers/gitlab/jira_import/import_issue_worker.rb @@ -15,8 +15,7 @@ module Gitlab loggable_arguments 3 def perform(project_id, jira_issue_id, issue_attributes, waiter_key) - issue_id = create_issue(issue_attributes, project_id) - JiraImport.cache_issue_mapping(issue_id, jira_issue_id, project_id) + create_issue(issue_attributes, project_id) rescue StandardError => ex # Todo: Record jira issue id(or better jira issue key), # so that we can report the list of failed to import issues to the user diff --git a/config/metrics/counts_all/20210216182855_package_events_i_package_composer_delete_package.yml b/config/metrics/counts_all/20210216182855_package_events_i_package_composer_delete_package.yml index 4db8a831afc..2db1ff225d8 100644 --- a/config/metrics/counts_all/20210216182855_package_events_i_package_composer_delete_package.yml +++ b/config/metrics/counts_all/20210216182855_package_events_i_package_composer_delete_package.yml @@ -10,6 +10,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_composer_delete_package distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216182857_package_events_i_package_composer_pull_package.yml b/config/metrics/counts_all/20210216182857_package_events_i_package_composer_pull_package.yml index cb1e984786c..81b381e7337 100644 --- a/config/metrics/counts_all/20210216182857_package_events_i_package_composer_pull_package.yml +++ b/config/metrics/counts_all/20210216182857_package_events_i_package_composer_pull_package.yml @@ -10,6 +10,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_composer_pull_package distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216182859_package_events_i_package_composer_push_package.yml b/config/metrics/counts_all/20210216182859_package_events_i_package_composer_push_package.yml index 0296f58dfb0..27e2b6ce535 100644 --- a/config/metrics/counts_all/20210216182859_package_events_i_package_composer_push_package.yml +++ b/config/metrics/counts_all/20210216182859_package_events_i_package_composer_push_package.yml @@ -10,6 +10,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_composer_push_package distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216182901_package_events_i_package_conan_delete_package.yml b/config/metrics/counts_all/20210216182901_package_events_i_package_conan_delete_package.yml index 7617489c5f4..90f0a59f58b 100644 --- a/config/metrics/counts_all/20210216182901_package_events_i_package_conan_delete_package.yml +++ b/config/metrics/counts_all/20210216182901_package_events_i_package_conan_delete_package.yml @@ -10,6 +10,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_conan_delete_package distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216182903_package_events_i_package_conan_pull_package.yml b/config/metrics/counts_all/20210216182903_package_events_i_package_conan_pull_package.yml index 125ef341824..be07d3a67c8 100644 --- a/config/metrics/counts_all/20210216182903_package_events_i_package_conan_pull_package.yml +++ b/config/metrics/counts_all/20210216182903_package_events_i_package_conan_pull_package.yml @@ -10,6 +10,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_conan_pull_package distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216182905_package_events_i_package_conan_push_package.yml b/config/metrics/counts_all/20210216182905_package_events_i_package_conan_push_package.yml index 3225658d982..deb3e1b4d0f 100644 --- a/config/metrics/counts_all/20210216182905_package_events_i_package_conan_push_package.yml +++ b/config/metrics/counts_all/20210216182905_package_events_i_package_conan_push_package.yml @@ -10,6 +10,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_conan_push_package distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216182913_package_events_i_package_debian_delete_package.yml b/config/metrics/counts_all/20210216182913_package_events_i_package_debian_delete_package.yml index 453f55a5e6a..e95a140aec9 100644 --- a/config/metrics/counts_all/20210216182913_package_events_i_package_debian_delete_package.yml +++ b/config/metrics/counts_all/20210216182913_package_events_i_package_debian_delete_package.yml @@ -10,6 +10,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_debian_delete_package distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216182915_package_events_i_package_debian_pull_package.yml b/config/metrics/counts_all/20210216182915_package_events_i_package_debian_pull_package.yml index 2949e819dff..f416d00ab4b 100644 --- a/config/metrics/counts_all/20210216182915_package_events_i_package_debian_pull_package.yml +++ b/config/metrics/counts_all/20210216182915_package_events_i_package_debian_pull_package.yml @@ -10,6 +10,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_debian_pull_package distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216182919_package_events_i_package_delete_package.yml b/config/metrics/counts_all/20210216182919_package_events_i_package_delete_package.yml index eeb5198e028..c5e999ae8f6 100644 --- a/config/metrics/counts_all/20210216182919_package_events_i_package_delete_package.yml +++ b/config/metrics/counts_all/20210216182919_package_events_i_package_delete_package.yml @@ -10,6 +10,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_delete_package distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216182921_package_events_i_package_delete_package_by_deploy_token.yml b/config/metrics/counts_all/20210216182921_package_events_i_package_delete_package_by_deploy_token.yml index 4d688af3908..7c160f02fee 100644 --- a/config/metrics/counts_all/20210216182921_package_events_i_package_delete_package_by_deploy_token.yml +++ b/config/metrics/counts_all/20210216182921_package_events_i_package_delete_package_by_deploy_token.yml @@ -10,6 +10,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_delete_package_by_deploy_token distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216182923_package_events_i_package_delete_package_by_guest.yml b/config/metrics/counts_all/20210216182923_package_events_i_package_delete_package_by_guest.yml index 9978595cb0a..b631d667ff0 100644 --- a/config/metrics/counts_all/20210216182923_package_events_i_package_delete_package_by_guest.yml +++ b/config/metrics/counts_all/20210216182923_package_events_i_package_delete_package_by_guest.yml @@ -10,6 +10,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_delete_package_by_guest distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216182925_package_events_i_package_delete_package_by_user.yml b/config/metrics/counts_all/20210216182925_package_events_i_package_delete_package_by_user.yml index 1e348c18943..3f62b79e9f1 100644 --- a/config/metrics/counts_all/20210216182925_package_events_i_package_delete_package_by_user.yml +++ b/config/metrics/counts_all/20210216182925_package_events_i_package_delete_package_by_user.yml @@ -10,6 +10,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_delete_package_by_user distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216182927_package_events_i_package_generic_delete_package.yml b/config/metrics/counts_all/20210216182927_package_events_i_package_generic_delete_package.yml index b88a0fe1622..82584ecd920 100644 --- a/config/metrics/counts_all/20210216182927_package_events_i_package_generic_delete_package.yml +++ b/config/metrics/counts_all/20210216182927_package_events_i_package_generic_delete_package.yml @@ -10,6 +10,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_generic_delete_package distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216182929_package_events_i_package_generic_pull_package.yml b/config/metrics/counts_all/20210216182929_package_events_i_package_generic_pull_package.yml index b2bcf1baffe..0eca0f41708 100644 --- a/config/metrics/counts_all/20210216182929_package_events_i_package_generic_pull_package.yml +++ b/config/metrics/counts_all/20210216182929_package_events_i_package_generic_pull_package.yml @@ -10,6 +10,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_generic_pull_package distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216182931_package_events_i_package_generic_push_package.yml b/config/metrics/counts_all/20210216182931_package_events_i_package_generic_push_package.yml index 54063d11b9f..1e3577820a4 100644 --- a/config/metrics/counts_all/20210216182931_package_events_i_package_generic_push_package.yml +++ b/config/metrics/counts_all/20210216182931_package_events_i_package_generic_push_package.yml @@ -10,6 +10,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_generic_push_package distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216182933_package_events_i_package_golang_delete_package.yml b/config/metrics/counts_all/20210216182933_package_events_i_package_golang_delete_package.yml index 0ea0007c525..8c0cfd62490 100644 --- a/config/metrics/counts_all/20210216182933_package_events_i_package_golang_delete_package.yml +++ b/config/metrics/counts_all/20210216182933_package_events_i_package_golang_delete_package.yml @@ -10,6 +10,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_golang_delete_package distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216182934_package_events_i_package_golang_pull_package.yml b/config/metrics/counts_all/20210216182934_package_events_i_package_golang_pull_package.yml index 1b68386e3fe..bd8b5ec54b7 100644 --- a/config/metrics/counts_all/20210216182934_package_events_i_package_golang_pull_package.yml +++ b/config/metrics/counts_all/20210216182934_package_events_i_package_golang_pull_package.yml @@ -10,6 +10,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_golang_pull_package distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216182936_package_events_i_package_golang_push_package.yml b/config/metrics/counts_all/20210216182936_package_events_i_package_golang_push_package.yml index be3f7974a44..0610ac36fab 100644 --- a/config/metrics/counts_all/20210216182936_package_events_i_package_golang_push_package.yml +++ b/config/metrics/counts_all/20210216182936_package_events_i_package_golang_push_package.yml @@ -10,6 +10,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_golang_push_package distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216182938_package_events_i_package_maven_delete_package.yml b/config/metrics/counts_all/20210216182938_package_events_i_package_maven_delete_package.yml index 676748442a5..1dfbdebfdc8 100644 --- a/config/metrics/counts_all/20210216182938_package_events_i_package_maven_delete_package.yml +++ b/config/metrics/counts_all/20210216182938_package_events_i_package_maven_delete_package.yml @@ -10,6 +10,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_maven_delete_package distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216182940_package_events_i_package_maven_pull_package.yml b/config/metrics/counts_all/20210216182940_package_events_i_package_maven_pull_package.yml index f035edcc74c..7e8891faa7a 100644 --- a/config/metrics/counts_all/20210216182940_package_events_i_package_maven_pull_package.yml +++ b/config/metrics/counts_all/20210216182940_package_events_i_package_maven_pull_package.yml @@ -10,6 +10,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_maven_pull_package distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216182942_package_events_i_package_maven_push_package.yml b/config/metrics/counts_all/20210216182942_package_events_i_package_maven_push_package.yml index 92521cc1fda..7685a116b9f 100644 --- a/config/metrics/counts_all/20210216182942_package_events_i_package_maven_push_package.yml +++ b/config/metrics/counts_all/20210216182942_package_events_i_package_maven_push_package.yml @@ -10,6 +10,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_maven_push_package distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216182944_package_events_i_package_npm_delete_package.yml b/config/metrics/counts_all/20210216182944_package_events_i_package_npm_delete_package.yml index 24188860b45..104576a8f32 100644 --- a/config/metrics/counts_all/20210216182944_package_events_i_package_npm_delete_package.yml +++ b/config/metrics/counts_all/20210216182944_package_events_i_package_npm_delete_package.yml @@ -10,6 +10,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_npm_delete_package distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216182946_package_events_i_package_npm_pull_package.yml b/config/metrics/counts_all/20210216182946_package_events_i_package_npm_pull_package.yml index 5dc94ab61fb..fe04fafc3c8 100644 --- a/config/metrics/counts_all/20210216182946_package_events_i_package_npm_pull_package.yml +++ b/config/metrics/counts_all/20210216182946_package_events_i_package_npm_pull_package.yml @@ -10,6 +10,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_npm_pull_package distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216182948_package_events_i_package_npm_push_package.yml b/config/metrics/counts_all/20210216182948_package_events_i_package_npm_push_package.yml index 0878ec9ade8..5f8ccc277f8 100644 --- a/config/metrics/counts_all/20210216182948_package_events_i_package_npm_push_package.yml +++ b/config/metrics/counts_all/20210216182948_package_events_i_package_npm_push_package.yml @@ -10,6 +10,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_npm_push_package distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216182950_package_events_i_package_nuget_delete_package.yml b/config/metrics/counts_all/20210216182950_package_events_i_package_nuget_delete_package.yml index bd45f8fd652..3570e509ce9 100644 --- a/config/metrics/counts_all/20210216182950_package_events_i_package_nuget_delete_package.yml +++ b/config/metrics/counts_all/20210216182950_package_events_i_package_nuget_delete_package.yml @@ -10,6 +10,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_nuget_delete_package distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216182952_package_events_i_package_nuget_pull_package.yml b/config/metrics/counts_all/20210216182952_package_events_i_package_nuget_pull_package.yml index e175f9ea64c..2eddb4af420 100644 --- a/config/metrics/counts_all/20210216182952_package_events_i_package_nuget_pull_package.yml +++ b/config/metrics/counts_all/20210216182952_package_events_i_package_nuget_pull_package.yml @@ -10,6 +10,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_nuget_pull_package distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216182954_package_events_i_package_nuget_push_package.yml b/config/metrics/counts_all/20210216182954_package_events_i_package_nuget_push_package.yml index 5e3c4d13177..02f45dad580 100644 --- a/config/metrics/counts_all/20210216182954_package_events_i_package_nuget_push_package.yml +++ b/config/metrics/counts_all/20210216182954_package_events_i_package_nuget_push_package.yml @@ -10,6 +10,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_nuget_push_package distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216182956_package_events_i_package_pull_package.yml b/config/metrics/counts_all/20210216182956_package_events_i_package_pull_package.yml index b059c11bf40..aa459c6db2c 100644 --- a/config/metrics/counts_all/20210216182956_package_events_i_package_pull_package.yml +++ b/config/metrics/counts_all/20210216182956_package_events_i_package_pull_package.yml @@ -10,6 +10,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_pull_package distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216182958_package_events_i_package_pull_package_by_deploy_token.yml b/config/metrics/counts_all/20210216182958_package_events_i_package_pull_package_by_deploy_token.yml index 532546fd7f3..a527379fe00 100644 --- a/config/metrics/counts_all/20210216182958_package_events_i_package_pull_package_by_deploy_token.yml +++ b/config/metrics/counts_all/20210216182958_package_events_i_package_pull_package_by_deploy_token.yml @@ -11,6 +11,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_pull_package_by_deploy_token distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216183000_package_events_i_package_pull_package_by_guest.yml b/config/metrics/counts_all/20210216183000_package_events_i_package_pull_package_by_guest.yml index d402d29612f..45dcd531484 100644 --- a/config/metrics/counts_all/20210216183000_package_events_i_package_pull_package_by_guest.yml +++ b/config/metrics/counts_all/20210216183000_package_events_i_package_pull_package_by_guest.yml @@ -11,6 +11,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_pull_package_by_guest distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216183002_package_events_i_package_pull_package_by_user.yml b/config/metrics/counts_all/20210216183002_package_events_i_package_pull_package_by_user.yml index 21076556ce4..69983e77d5f 100644 --- a/config/metrics/counts_all/20210216183002_package_events_i_package_pull_package_by_user.yml +++ b/config/metrics/counts_all/20210216183002_package_events_i_package_pull_package_by_user.yml @@ -11,6 +11,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_pull_package_by_user distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216183004_package_events_i_package_push_package.yml b/config/metrics/counts_all/20210216183004_package_events_i_package_push_package.yml index c9f52de010b..22c4969ad7d 100644 --- a/config/metrics/counts_all/20210216183004_package_events_i_package_push_package.yml +++ b/config/metrics/counts_all/20210216183004_package_events_i_package_push_package.yml @@ -10,6 +10,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_push_package distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216183005_package_events_i_package_push_package_by_deploy_token.yml b/config/metrics/counts_all/20210216183005_package_events_i_package_push_package_by_deploy_token.yml index cf0c42dce28..252474155c1 100644 --- a/config/metrics/counts_all/20210216183005_package_events_i_package_push_package_by_deploy_token.yml +++ b/config/metrics/counts_all/20210216183005_package_events_i_package_push_package_by_deploy_token.yml @@ -11,6 +11,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_push_package_by_deploy_token distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216183007_package_events_i_package_push_package_by_guest.yml b/config/metrics/counts_all/20210216183007_package_events_i_package_push_package_by_guest.yml index 92d31d03faa..8fa5f2b877c 100644 --- a/config/metrics/counts_all/20210216183007_package_events_i_package_push_package_by_guest.yml +++ b/config/metrics/counts_all/20210216183007_package_events_i_package_push_package_by_guest.yml @@ -11,6 +11,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_push_package_by_guest distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216183009_package_events_i_package_push_package_by_user.yml b/config/metrics/counts_all/20210216183009_package_events_i_package_push_package_by_user.yml index 1a3b14e8a0b..42b0b0130ad 100644 --- a/config/metrics/counts_all/20210216183009_package_events_i_package_push_package_by_user.yml +++ b/config/metrics/counts_all/20210216183009_package_events_i_package_push_package_by_user.yml @@ -11,6 +11,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_push_package_by_user distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216183011_package_events_i_package_pypi_delete_package.yml b/config/metrics/counts_all/20210216183011_package_events_i_package_pypi_delete_package.yml index 6c0e86090ae..d1c7f71e593 100644 --- a/config/metrics/counts_all/20210216183011_package_events_i_package_pypi_delete_package.yml +++ b/config/metrics/counts_all/20210216183011_package_events_i_package_pypi_delete_package.yml @@ -10,6 +10,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_pypi_delete_package distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216183013_package_events_i_package_pypi_pull_package.yml b/config/metrics/counts_all/20210216183013_package_events_i_package_pypi_pull_package.yml index 2512818a4e1..e47231a30bd 100644 --- a/config/metrics/counts_all/20210216183013_package_events_i_package_pypi_pull_package.yml +++ b/config/metrics/counts_all/20210216183013_package_events_i_package_pypi_pull_package.yml @@ -11,6 +11,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_pypi_pull_package distribution: - ee - ce diff --git a/config/metrics/counts_all/20210216183015_package_events_i_package_pypi_push_package.yml b/config/metrics/counts_all/20210216183015_package_events_i_package_pypi_push_package.yml index 4234dd52964..4edd359cc1e 100644 --- a/config/metrics/counts_all/20210216183015_package_events_i_package_pypi_push_package.yml +++ b/config/metrics/counts_all/20210216183015_package_events_i_package_pypi_push_package.yml @@ -10,6 +10,10 @@ value_type: number status: active time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_pypi_push_package distribution: - ee - ce diff --git a/config/metrics/counts_all/20210303153000_package_events_i_package_rubygems_delete_package.yml b/config/metrics/counts_all/20210303153000_package_events_i_package_rubygems_delete_package.yml index 15f3003f5d6..2265eff7393 100644 --- a/config/metrics/counts_all/20210303153000_package_events_i_package_rubygems_delete_package.yml +++ b/config/metrics/counts_all/20210303153000_package_events_i_package_rubygems_delete_package.yml @@ -12,6 +12,10 @@ milestone: '13.10' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53480 time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_rubygems_delete_package distribution: - ce - ee diff --git a/config/metrics/counts_all/20210303153002_package_events_i_package_rubygems_pull_package.yml b/config/metrics/counts_all/20210303153002_package_events_i_package_rubygems_pull_package.yml index 5c825c76296..20af7e2a564 100644 --- a/config/metrics/counts_all/20210303153002_package_events_i_package_rubygems_pull_package.yml +++ b/config/metrics/counts_all/20210303153002_package_events_i_package_rubygems_pull_package.yml @@ -12,6 +12,10 @@ milestone: '13.10' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53480 time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_rubygems_pull_package distribution: - ce - ee diff --git a/config/metrics/counts_all/20210303153004_package_events_i_package_rubygems_push_package.yml b/config/metrics/counts_all/20210303153004_package_events_i_package_rubygems_push_package.yml index f8a8fcf8abd..6c7150b3f44 100644 --- a/config/metrics/counts_all/20210303153004_package_events_i_package_rubygems_push_package.yml +++ b/config/metrics/counts_all/20210303153004_package_events_i_package_rubygems_push_package.yml @@ -12,6 +12,10 @@ time_frame: all milestone: '13.10' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53480 data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_rubygems_push_package distribution: - ce - ee diff --git a/config/metrics/counts_all/20210410012200_package_events_i_package_terraform_module_delete_package.yml b/config/metrics/counts_all/20210410012200_package_events_i_package_terraform_module_delete_package.yml index b914a60050d..2dd4576a0fc 100644 --- a/config/metrics/counts_all/20210410012200_package_events_i_package_terraform_module_delete_package.yml +++ b/config/metrics/counts_all/20210410012200_package_events_i_package_terraform_module_delete_package.yml @@ -12,6 +12,10 @@ milestone: '13.11' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55018 time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_terraform_module_delete_package distribution: - ce - ee diff --git a/config/metrics/counts_all/20210410012202_package_events_i_package_terraform_module_pull_package.yml b/config/metrics/counts_all/20210410012202_package_events_i_package_terraform_module_pull_package.yml index 85258f27878..21b36947f1a 100644 --- a/config/metrics/counts_all/20210410012202_package_events_i_package_terraform_module_pull_package.yml +++ b/config/metrics/counts_all/20210410012202_package_events_i_package_terraform_module_pull_package.yml @@ -12,6 +12,10 @@ milestone: '13.11' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55018 time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_terraform_module_pull_package distribution: - ce - ee diff --git a/config/metrics/counts_all/20210410012204_package_events_i_package_terraform_module_push_package.yml b/config/metrics/counts_all/20210410012204_package_events_i_package_terraform_module_push_package.yml index f8d0643ab3a..bd7a26f022b 100644 --- a/config/metrics/counts_all/20210410012204_package_events_i_package_terraform_module_push_package.yml +++ b/config/metrics/counts_all/20210410012204_package_events_i_package_terraform_module_push_package.yml @@ -12,6 +12,10 @@ milestone: '13.11' introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55018 time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_terraform_module_push_package distribution: - ce - ee diff --git a/config/metrics/counts_all/20210517073546_package_events_i_package_helm_pull_package.yml b/config/metrics/counts_all/20210517073546_package_events_i_package_helm_pull_package.yml index 04cc4a17b45..f2bbac01b47 100644 --- a/config/metrics/counts_all/20210517073546_package_events_i_package_helm_pull_package.yml +++ b/config/metrics/counts_all/20210517073546_package_events_i_package_helm_pull_package.yml @@ -12,6 +12,10 @@ milestone: "14.0" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61014 time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_helm_pull_package distribution: - ce - ee diff --git a/config/metrics/counts_all/20210625095025_package_events_i_package_helm_push_package.yml b/config/metrics/counts_all/20210625095025_package_events_i_package_helm_push_package.yml index c529f1ecb8a..5be5a703ad4 100644 --- a/config/metrics/counts_all/20210625095025_package_events_i_package_helm_push_package.yml +++ b/config/metrics/counts_all/20210625095025_package_events_i_package_helm_push_package.yml @@ -11,6 +11,10 @@ milestone: "14.1" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64814 time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_helm_push_package data_category: optional distribution: - ce diff --git a/config/metrics/counts_all/20210709191135_package_events_i_package_nuget_pull_symbol_package.yml b/config/metrics/counts_all/20210709191135_package_events_i_package_nuget_pull_symbol_package.yml index 164cdd477cb..9924df439b0 100644 --- a/config/metrics/counts_all/20210709191135_package_events_i_package_nuget_pull_symbol_package.yml +++ b/config/metrics/counts_all/20210709191135_package_events_i_package_nuget_pull_symbol_package.yml @@ -12,6 +12,10 @@ milestone: "14.1" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64554 time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_nuget_pull_symbol_package data_category: optional distribution: - ce diff --git a/config/metrics/counts_all/20210709191829_package_events_i_package_nuget_push_symbol_package.yml b/config/metrics/counts_all/20210709191829_package_events_i_package_nuget_push_symbol_package.yml index eb9576c864c..ecff5ad53e0 100644 --- a/config/metrics/counts_all/20210709191829_package_events_i_package_nuget_push_symbol_package.yml +++ b/config/metrics/counts_all/20210709191829_package_events_i_package_nuget_push_symbol_package.yml @@ -12,6 +12,10 @@ milestone: "14.1" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64554 time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_nuget_push_symbol_package data_category: optional distribution: - ce diff --git a/config/metrics/counts_all/20210709210941_package_events_i_package_pull_symbol_package.yml b/config/metrics/counts_all/20210709210941_package_events_i_package_pull_symbol_package.yml index 712eeb644cc..e7f3491aa09 100644 --- a/config/metrics/counts_all/20210709210941_package_events_i_package_pull_symbol_package.yml +++ b/config/metrics/counts_all/20210709210941_package_events_i_package_pull_symbol_package.yml @@ -12,6 +12,10 @@ milestone: "14.1" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64554 time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_pull_symbol_package data_category: optional distribution: - ce diff --git a/config/metrics/counts_all/20210709211058_package_events_i_package_pull_symbol_package_by_deploy_token.yml b/config/metrics/counts_all/20210709211058_package_events_i_package_pull_symbol_package_by_deploy_token.yml index d4ebb18d006..6aaf9bc2978 100644 --- a/config/metrics/counts_all/20210709211058_package_events_i_package_pull_symbol_package_by_deploy_token.yml +++ b/config/metrics/counts_all/20210709211058_package_events_i_package_pull_symbol_package_by_deploy_token.yml @@ -12,6 +12,10 @@ milestone: "14.1" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64554 time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_pull_symbol_package_by_deploy_token data_category: optional distribution: - ce diff --git a/config/metrics/counts_all/20210709211248_package_events_i_package_pull_symbol_package_by_guest.yml b/config/metrics/counts_all/20210709211248_package_events_i_package_pull_symbol_package_by_guest.yml index d84a218e88e..936e245c240 100644 --- a/config/metrics/counts_all/20210709211248_package_events_i_package_pull_symbol_package_by_guest.yml +++ b/config/metrics/counts_all/20210709211248_package_events_i_package_pull_symbol_package_by_guest.yml @@ -12,6 +12,10 @@ milestone: "14.1" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64554 time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_pull_symbol_package_by_guest data_category: optional distribution: - ce diff --git a/config/metrics/counts_all/20210709211341_package_events_i_package_pull_symbol_package_by_user.yml b/config/metrics/counts_all/20210709211341_package_events_i_package_pull_symbol_package_by_user.yml index b91dfa334a5..373c23a4016 100644 --- a/config/metrics/counts_all/20210709211341_package_events_i_package_pull_symbol_package_by_user.yml +++ b/config/metrics/counts_all/20210709211341_package_events_i_package_pull_symbol_package_by_user.yml @@ -12,6 +12,10 @@ milestone: "14.1" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64554 time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_pull_symbol_package_by_user data_category: optional distribution: - ce diff --git a/config/metrics/counts_all/20210709211439_package_events_i_package_push_symbol_package.yml b/config/metrics/counts_all/20210709211439_package_events_i_package_push_symbol_package.yml index a6335011ddd..e1c08134dec 100644 --- a/config/metrics/counts_all/20210709211439_package_events_i_package_push_symbol_package.yml +++ b/config/metrics/counts_all/20210709211439_package_events_i_package_push_symbol_package.yml @@ -12,6 +12,10 @@ milestone: "14.1" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64554 time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_push_symbol_package data_category: optional distribution: - ce diff --git a/config/metrics/counts_all/20210709211636_package_events_i_package_push_symbol_package_by_deploy_token.yml b/config/metrics/counts_all/20210709211636_package_events_i_package_push_symbol_package_by_deploy_token.yml index acc00f50744..2cdfc6f86d0 100644 --- a/config/metrics/counts_all/20210709211636_package_events_i_package_push_symbol_package_by_deploy_token.yml +++ b/config/metrics/counts_all/20210709211636_package_events_i_package_push_symbol_package_by_deploy_token.yml @@ -12,6 +12,10 @@ milestone: "14.1" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64554 time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_push_symbol_package_by_deploy_token data_category: optional distribution: - ce diff --git a/config/metrics/counts_all/20210709211731_package_events_i_package_push_symbol_package_by_guest.yml b/config/metrics/counts_all/20210709211731_package_events_i_package_push_symbol_package_by_guest.yml index 16635a5f6a9..69db39047c7 100644 --- a/config/metrics/counts_all/20210709211731_package_events_i_package_push_symbol_package_by_guest.yml +++ b/config/metrics/counts_all/20210709211731_package_events_i_package_push_symbol_package_by_guest.yml @@ -12,6 +12,10 @@ milestone: "14.1" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64554 time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_push_symbol_package_by_guest data_category: optional distribution: - ce diff --git a/config/metrics/counts_all/20210709211831_package_events_i_package_push_symbol_package_by_user.yml b/config/metrics/counts_all/20210709211831_package_events_i_package_push_symbol_package_by_user.yml index 653814c4bf0..d7fd850a24f 100644 --- a/config/metrics/counts_all/20210709211831_package_events_i_package_push_symbol_package_by_user.yml +++ b/config/metrics/counts_all/20210709211831_package_events_i_package_push_symbol_package_by_user.yml @@ -12,6 +12,10 @@ milestone: "14.1" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64554 time_frame: all data_source: redis +instrumentation_class: RedisMetric +options: + prefix: package_events + event: i_package_push_symbol_package_by_user data_category: optional distribution: - ce diff --git a/db/migrate/20220824175648_limit_namespaces_sync_triggers_to_traversal_ids_update.rb b/db/migrate/20220824175648_limit_namespaces_sync_triggers_to_traversal_ids_update.rb new file mode 100644 index 00000000000..142744b5493 --- /dev/null +++ b/db/migrate/20220824175648_limit_namespaces_sync_triggers_to_traversal_ids_update.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +class LimitNamespacesSyncTriggersToTraversalIdsUpdate < Gitlab::Database::Migration[2.0] + include Gitlab::Database::SchemaHelpers + + enable_lock_retries! + + TABLE_NAME = 'namespaces' + EVENT_TABLE_NAME = 'namespaces_sync_events' + FUNCTION_NAME = 'insert_namespaces_sync_event' + OLD_TRIGGER_ON_INSERT = 'trigger_namespaces_parent_id_on_insert' + OLD_TRIGGER_ON_UPDATE = 'trigger_namespaces_parent_id_on_update' + NEW_TRIGGER_ON_UPDATE = 'trigger_namespaces_traversal_ids_on_update' + + def up + create_trigger(TABLE_NAME, NEW_TRIGGER_ON_UPDATE, FUNCTION_NAME, fires: 'AFTER UPDATE') do + <<~SQL + WHEN (OLD.traversal_ids IS DISTINCT FROM NEW.traversal_ids) + SQL + end + drop_trigger(TABLE_NAME, OLD_TRIGGER_ON_UPDATE) + drop_trigger(TABLE_NAME, OLD_TRIGGER_ON_INSERT) + end + + # Revert both triggers to the version defined in db/migrate/20211011141242_create_namespaces_sync_trigger.rb + def down + create_trigger(TABLE_NAME, OLD_TRIGGER_ON_INSERT, FUNCTION_NAME, fires: 'AFTER INSERT') + create_trigger(TABLE_NAME, OLD_TRIGGER_ON_UPDATE, FUNCTION_NAME, fires: 'AFTER UPDATE') do + <<~SQL + WHEN (OLD.parent_id IS DISTINCT FROM NEW.parent_id) + SQL + end + drop_trigger(TABLE_NAME, NEW_TRIGGER_ON_UPDATE) + end +end diff --git a/db/migrate/20220907124320_add_internal_to_notes.rb b/db/migrate/20220907124320_add_internal_to_notes.rb new file mode 100644 index 00000000000..081914f7830 --- /dev/null +++ b/db/migrate/20220907124320_add_internal_to_notes.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +class AddInternalToNotes < Gitlab::Database::Migration[2.0] + enable_lock_retries! + + def change + add_column(:notes, :internal, :boolean, default: false, null: false) + end +end diff --git a/db/post_migrate/20220912110433_prepare_create_internal_notes_index_on_id.rb b/db/post_migrate/20220912110433_prepare_create_internal_notes_index_on_id.rb new file mode 100644 index 00000000000..241bdfa4715 --- /dev/null +++ b/db/post_migrate/20220912110433_prepare_create_internal_notes_index_on_id.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class PrepareCreateInternalNotesIndexOnId < Gitlab::Database::Migration[2.0] + INDEX_NAME = 'index_notes_on_id_where_internal' + + def up + prepare_async_index :notes, :id, where: 'internal = true', name: INDEX_NAME + end + + def down + unprepare_async_index_by_name :notes, INDEX_NAME + end +end diff --git a/db/schema_migrations/20220824175648 b/db/schema_migrations/20220824175648 new file mode 100644 index 00000000000..7a54d9c2a41 --- /dev/null +++ b/db/schema_migrations/20220824175648 @@ -0,0 +1 @@ +5f2c56f9dd6f7ddbf34718f37fc9c37dfd9afeeae9cd2efb9fd465874b6ea8c0
\ No newline at end of file diff --git a/db/schema_migrations/20220907124320 b/db/schema_migrations/20220907124320 new file mode 100644 index 00000000000..59077465bf9 --- /dev/null +++ b/db/schema_migrations/20220907124320 @@ -0,0 +1 @@ +5b645f66351e9515826be882767ad07671b7b5fad7b942bc74325b05c84130ac
\ No newline at end of file diff --git a/db/schema_migrations/20220912110433 b/db/schema_migrations/20220912110433 new file mode 100644 index 00000000000..0e31168be7d --- /dev/null +++ b/db/schema_migrations/20220912110433 @@ -0,0 +1 @@ +3bf30b096f71664f5bfae88cc21b1d7992ebcbbb6eb9eb15348bc689291bffd2
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 8618e12193b..ae5fb74d8f2 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -18061,7 +18061,8 @@ CREATE TABLE notes ( resolved_by_push boolean, review_id bigint, confidential boolean, - last_edited_at timestamp with time zone + last_edited_at timestamp with time zone, + internal boolean DEFAULT false NOT NULL ); CREATE SEQUENCE notes_id_seq @@ -32220,9 +32221,7 @@ CREATE TRIGGER trigger_insert_or_update_vulnerability_reads_from_occurrences AFT CREATE TRIGGER trigger_insert_vulnerability_reads_from_vulnerability AFTER UPDATE ON vulnerabilities FOR EACH ROW WHEN (((old.present_on_default_branch IS NOT TRUE) AND (new.present_on_default_branch IS TRUE))) EXECUTE FUNCTION insert_vulnerability_reads_from_vulnerability(); -CREATE TRIGGER trigger_namespaces_parent_id_on_insert AFTER INSERT ON namespaces FOR EACH ROW EXECUTE FUNCTION insert_namespaces_sync_event(); - -CREATE TRIGGER trigger_namespaces_parent_id_on_update AFTER UPDATE ON namespaces FOR EACH ROW WHEN ((old.parent_id IS DISTINCT FROM new.parent_id)) EXECUTE FUNCTION insert_namespaces_sync_event(); +CREATE TRIGGER trigger_namespaces_traversal_ids_on_update AFTER UPDATE ON namespaces FOR EACH ROW WHEN ((old.traversal_ids IS DISTINCT FROM new.traversal_ids)) EXECUTE FUNCTION insert_namespaces_sync_event(); CREATE TRIGGER trigger_projects_parent_id_on_insert AFTER INSERT ON projects FOR EACH ROW EXECUTE FUNCTION insert_projects_sync_event(); diff --git a/doc/administration/audit_event_streaming.md b/doc/administration/audit_event_streaming.md index 9b1bf1f92dd..71ec916d2a3 100644 --- a/doc/administration/audit_event_streaming.md +++ b/doc/administration/audit_event_streaming.md @@ -1,5 +1,5 @@ --- -stage: Manage +stage: Govern group: Compliance info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- diff --git a/doc/administration/audit_events.md b/doc/administration/audit_events.md index 822d1087fbf..47b8de2440b 100644 --- a/doc/administration/audit_events.md +++ b/doc/administration/audit_events.md @@ -1,5 +1,5 @@ --- -stage: Manage +stage: Govern group: Compliance info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- diff --git a/doc/administration/audit_reports.md b/doc/administration/audit_reports.md index e33b5153c5b..e363e7862ea 100644 --- a/doc/administration/audit_reports.md +++ b/doc/administration/audit_reports.md @@ -1,5 +1,5 @@ --- -stage: Manage +stage: Govern group: Compliance info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments description: 'Learn how to create evidence artifacts typically requested by a 3rd party auditor.' diff --git a/doc/administration/compliance.md b/doc/administration/compliance.md index 8c7f8bf766d..573ffbf4686 100644 --- a/doc/administration/compliance.md +++ b/doc/administration/compliance.md @@ -1,5 +1,5 @@ --- -stage: Manage +stage: Govern group: Compliance info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- diff --git a/doc/administration/inactive_project_deletion.md b/doc/administration/inactive_project_deletion.md index e3e57d12dd9..824a444fdd2 100644 --- a/doc/administration/inactive_project_deletion.md +++ b/doc/administration/inactive_project_deletion.md @@ -1,5 +1,5 @@ --- -stage: Manage +stage: Govern group: Compliance info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- diff --git a/doc/api/audit_events.md b/doc/api/audit_events.md index 80d7b23d642..5bff3cf49fc 100644 --- a/doc/api/audit_events.md +++ b/doc/api/audit_events.md @@ -1,5 +1,5 @@ --- -stage: Manage +stage: Govern group: Compliance info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- diff --git a/doc/api/events.md b/doc/api/events.md index 3f032c72870..e4490459030 100644 --- a/doc/api/events.md +++ b/doc/api/events.md @@ -1,5 +1,5 @@ --- -stage: Manage +stage: Govern group: Compliance info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- diff --git a/doc/api/personal_access_tokens.md b/doc/api/personal_access_tokens.md index 7dc31c3f9f0..849b5c75684 100644 --- a/doc/api/personal_access_tokens.md +++ b/doc/api/personal_access_tokens.md @@ -1,5 +1,5 @@ --- -stage: Manage +stage: Govern group: Compliance info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- diff --git a/doc/api/resource_label_events.md b/doc/api/resource_label_events.md index 9c05d32c992..da265972f28 100644 --- a/doc/api/resource_label_events.md +++ b/doc/api/resource_label_events.md @@ -1,5 +1,5 @@ --- -stage: Manage +stage: Govern group: Compliance info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- diff --git a/doc/api/status_checks.md b/doc/api/status_checks.md index 92e003bf80d..1cedd2d3730 100644 --- a/doc/api/status_checks.md +++ b/doc/api/status_checks.md @@ -1,5 +1,5 @@ --- -stage: Manage +stage: Govern group: Compliance info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments" type: reference, api diff --git a/doc/api/vulnerabilities.md b/doc/api/vulnerabilities.md index 66d0579bacb..c90dc226661 100644 --- a/doc/api/vulnerabilities.md +++ b/doc/api/vulnerabilities.md @@ -1,5 +1,5 @@ --- -stage: Secure +stage: Govern group: Threat Insights info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- diff --git a/doc/api/vulnerability_exports.md b/doc/api/vulnerability_exports.md index 6f6a661dbd5..59943ede3e6 100644 --- a/doc/api/vulnerability_exports.md +++ b/doc/api/vulnerability_exports.md @@ -1,5 +1,5 @@ --- -stage: Secure +stage: Govern group: Threat Insights info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- diff --git a/doc/api/vulnerability_findings.md b/doc/api/vulnerability_findings.md index 46479009d7d..fcfef848f14 100644 --- a/doc/api/vulnerability_findings.md +++ b/doc/api/vulnerability_findings.md @@ -1,5 +1,5 @@ --- -stage: Secure +stage: Govern group: Threat Insights info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- diff --git a/doc/architecture/blueprints/ci_pipeline_components/index.md b/doc/architecture/blueprints/ci_pipeline_components/index.md new file mode 100644 index 00000000000..94ec3e2f894 --- /dev/null +++ b/doc/architecture/blueprints/ci_pipeline_components/index.md @@ -0,0 +1,209 @@ +--- +stage: Stage +group: Pipeline Authoring +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +comments: false +description: 'Create a catalog of shareable pipeline constructs' +--- + + +# CI/CD pipeline components catalog + +## Summary + +## Goals + +The goal of the CI/CD pipeline components catalog is to make the reusing pipeline configurations +easier and more efficient. +Providing a way to discover, understand and learn how to reuse pipeline constructs allows for a more streamlined experience. +Having a CI/CD pipeline components catalog also sets a framework for users to collaborate on pipeline constructs so that they can be evolved +and improved over time. + +This blueprint defines the architectural guidelines on how to build a CI/CD catalog of pipeline components. +This blueprint also defines the long-term direction for iterations and improvements to the solution. + +## Challenges + +- GitLab CI/CD can have a steep learning curve for new users. Users must read the documentation and + [YAML reference](../../../ci/yaml/index.md) to understand how to configure their pipelines. +- Developers are struggling to reuse existing CI/CD templates with the result of having to reinvent the wheel and write + YAML configurations repeatedly. +- GitLab [CI templates](../../../development/cicd/templates.md#template-directories) provide users with + scaffolding pipeline or jobs for specific purposes. + However versioning them is challenging today due to being shipped with the GitLab instance. + See [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/17716) for more information. +- Users of GitLab CI/CD (pipeline authors) today have their own ad-hoc way to organize shared pipeline + configurations inside their organization. Those configurations tend to be mostly undocumented. +- The only discoverable configurations are GitLab CI templates. However they don't have any inline documentation + so it becomes harder to know what they do and how to use them without copy-pasting the content in the + editor and read the actual YAML. +- It's harder to adopt additional GitLab features (CD, security, test, etc.). +- There is no framework for testing reusable CI configurations. + Many configurations are not unit tested against single changes. +- Communities, partners, 3rd parties, individual contributors, must go through the + [GitLab Contribution process](https://about.gitlab.com/community/contribute/) to contribute to GitLab managed + templates. See [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/323727) for more information. +- GitLab has more than 100 of templates with some of them barely maintained after their addition. + +### Problems with GitLab CI templates + +- GitLab CI Templates have not been designed with deterministic behavior in mind. +- GitLab CI Templates have not been design with reusability in mind. +- `Jobs/` templates hard-code the `stage:` attribute but the user of the template must somehow override + or know in advance what stage is needed. + - The user should be able to import the job inside a given stage or pass the stage names as input parameter + when using the component. + - Failures in mapping the correct stage can result in confusing errors. +- Some templates are designed to work with AutoDevops but are not generic enough + ([example](https://gitlab.com/gitlab-org/gitlab/-/blob/2c0e8e4470001442e999391df81e19732b3439e6/lib/gitlab/ci/templates/AWS/Deploy-ECS.gitlab-ci.yml)). +- Many CI templates, especially those [language specific](https://gitlab.com/gitlab-org/gitlab/-/tree/2c0e8e4470001442e999391df81e19732b3439e6/lib/gitlab/ci/templates) + are tutorial/scaffolding-style templates. + - They are meant to show the user how a typical pipeline would look like but it requires high customization from the user perspective. + - They require a different UX: copy-paste in the position of the Pipeline Editor cursor. +- Some templates like `SAST.latest.gitlab-ci.yml` add multiple jobs conditionally to the same pipeline. + - Ideally these jobs could run as a child pipeline and make the reports available to the parent pipeline. + - [This epic](https://gitlab.com/groups/gitlab-org/-/epics/8205) is necessary for Parent-child pipelines to be used. +- Some templates incorrectly use `variables`, `image` and other top-level keywords but that defines them in all pipeline jobs, + not just those defined in the template. + - This technique introduces inheritance issues when a template modifies jobs unnecessarily. + +## Opportunities + +- Having a catalog of pipeline constructs where users can search and find what they need can greatly lower + the bar for new users. +- Customers are already trying to rollout their ad-hoc catalog of shared configurations. We could provide a + standardized way to write, package and share pipeline constructs directly in the product. +- As we implement new pipeline constructs (for example, reusable job steps) they could be items of the + catalog. The catalog can boost the adoption of new constructs. +- The catalog can be a place where we strengthen our relationship with partners, having components offered + and maintained by our partners. +- With discoverability and better versioning mechanism we can have more improvements and better collaboration. +- Competitive landscape is showing the need for such feature + - [R2DevOps](https://r2devops.io) implements a catalog of CI templates for GitLab pipelines. + - [GitHub Actions](https://github.com/features/actions) provides an extensive catalog of reusable job steps. + +## Implementation guidelines + +- Start with the smallest user base. Dogfood the feature for `gitlab-org` and `gitlab-com` groups. + Involve the Engineering Productivity and other groups authoring pipeline configurations to test + and validate our solutions. +- Ensure we can integrate all the feedback gathered, even if that means changing the technical design or + UX. Until we make the feature GA we should have clear expectations with early adopters. +- Reuse existing functionality as much as possible. Don't reinvent the wheel on the initial iterations. + For example: reuse project features like title, description, avatar to build a catalog. +- Leverage GitLab features for the development lifecycle of the components (testing via `.gitlab-ci.yml`, + release management, Pipeline Editor, etc.). +- Design the catalog with self-managed support in mind. +- Allow the catalog an the workflow to support future types of pipeline constructs and new ways of using them. +- Design components and catalog following industry best practice related to building deterministic package managers. + +## Glossary + +This section defines some terms that are used throughout this document. With these terms we are only +identifying abstract concepts and are subject to changes as we refine the design by discovering new insights. + +- **Component** Is the reusable unit of pipeline configuration. +- **Project** Is the GitLab project attached to a repository. A project can contain multiple components. +- **Catalog** is the collection of projects that are set to contain components. +- **Version** is the release name of a tag in the project, which allows components to be pinned to a specific revision. + +## Characteristics of a component + +For best experience with any systems made of components it's fundamental that components are single purpose, +isolated, reusable and resolvable. + +- **Single purpose**: a component must focus on a single goal and the scope be as small as possible. +- **Isolation**: when a component is used in a pipeline, its implementation details should not leak outside the + component itself and into the main pipeline. +- **Reusability:** a component is designed to be used in different pipelines. + Depending on the assumptions it's built on a component can be more or less generic. + Generic components are more reusable but may require more customization. +- **Resolvable:** When a component depends on another component, this dependency needs to be explicit and trackable. Hidden dependencies can lead to myriads of problems. + +## Proposal + +Prerequisites to create a component: + +- Create a project. Description and avatar are highly recommended to improve discoverability. +- Add a `README.md` in the top level directory that documents the component. + What it does, how to use it, how to contribute, etc. + This file is mandatory. +- Add a `.gitlab-ci.yml` in the top level directory to test that the components works as expected. + This file is highly recommended. + +Characteristics of a component: + +- It must have a **name** to be referenced to and **description** for extra details. +- It must specify its **type** which defines how it can be used (raw configuration to be `include`d, child pipeline workflow, job step). +- It must define its **content** based on the type. +- It must specify **input parameters** that it accepts. Components should depend on input parameters for dynamic values and not environment variables. +- It can optionally define **output data** that it returns. +- Its YAML specification should be **validated statically** (for example: using JSON schema validators). +- It should be possible to use specific **versions** of a component by referencing official releases and SHA. +- It should be possible to use components defined locally in the same repository. + +## Limits + +Any MVC that exposes a feature should be added with limitations from the beginning. +It's safer to add new features with restrictions than trying to limit a feature after it's being used. +We can always soften the restrictions later depending on user demand. + +Some limits we could consider adding: + +- number of components that a single project can contain/export +- number of imports that a `.gitlab-ci.yml` file can use +- number of imports that a component can declare/use +- max level of nested imports +- max length of the exported component name + +## Iterations + +1. Experimentation phase + - Build an MVC behind a feature flag with `namespace` actor. + - Enable the feature flag only for `gitlab-com` and `gitlab-org` namespaces to initiate the dogfooding. + - Refine the solution and UX based on feedback. + - Find customers to be early adopters of this feature and iterate on their feedback. +1. Design new pipeline constructs (in parallel with other phases) + - Start the technical and design process to work on proposals for new pipeline constructs (steps, workflows, templates). + - Implement new constructs. The catalog must be compatible with them. + - Dogfood new constructs and iterate on feedback. + - Release new constructs on private catalogs. +1. Release the private catalog for groups on Ultimate plan. + - Iterate on feedback. +1. Release the public catalog for all GitLab users (prospect feature) + - Publish new versions of GitLab CI templates as components using the new constructs whenever possible. + - Allow self-managed administrators to populate their self-managed catalog by importing/updating + components from GitLab.com or from repository exports. + - Iterate on feedback. + +## Who + +Proposal: + +<!-- vale gitlab.Spelling = NO --> + +| Role | Who +|------------------------------|-------------------------| +| Author | Fabio Pitino | +| Engineering Leader | ? | +| Product Manager | Dov Hershkovitch | +| Architecture Evolution Coach | Kamil Trzciński | + +DRIs: + +| Role | Who +|------------------------------|------------------------| +| Leadership | ? | +| Product | Dov Hershkovitch | +| Engineering | ? | +| UX | Nadia Sotnikova | + +Domain experts: + +| Area | Who +|------------------------------|------------------------| +| Verify / Pipeline authoring | Avielle Wolfe | +| Verify / Pipeline authoring | Furkan Ayhan | +| Verify / Pipeline execution | Fabio Pitino | + +<!-- vale gitlab.Spelling = YES --> diff --git a/doc/development/audit_event_guide/index.md b/doc/development/audit_event_guide/index.md index 4efc65ce0e7..50d7eeed107 100644 --- a/doc/development/audit_event_guide/index.md +++ b/doc/development/audit_event_guide/index.md @@ -1,5 +1,5 @@ --- -stage: Manage +stage: Govern group: Compliance info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- diff --git a/doc/development/integrations/secure.md b/doc/development/integrations/secure.md index f7458a8462d..2c5dd1c0500 100644 --- a/doc/development/integrations/secure.md +++ b/doc/development/integrations/secure.md @@ -1,6 +1,6 @@ --- -stage: Protect -group: Container Security +stage: Secure +group: Static Analysis info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- diff --git a/doc/integration/advanced_search/elasticsearch.md b/doc/integration/advanced_search/elasticsearch.md index 93118cc7eb2..755dc5230e9 100644 --- a/doc/integration/advanced_search/elasticsearch.md +++ b/doc/integration/advanced_search/elasticsearch.md @@ -175,7 +175,7 @@ For GitLab instances with more than 50GB repository data you can follow the inst To enable Advanced Search, you must have administrator access to GitLab: -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > Advanced Search**. NOTE: @@ -271,7 +271,7 @@ You can improve the language support for Chinese and Japanese languages by utili To enable languages support: 1. Install the desired plugins, please refer to [Elasticsearch documentation](https://www.elastic.co/guide/en/elasticsearch/plugins/7.9/installation.html) for plugins installation instructions. The plugins must be installed on every node in the cluster, and each node must be restarted after installation. For a list of plugins, see the table later in this section. -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > Advanced Search**. 1. Locate **Custom analyzers: language support**. 1. Enable plugins support for **Indexing**. @@ -292,7 +292,7 @@ For guidance on what to install, see the following Elasticsearch language plugin To disable the Elasticsearch integration: -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > Advanced Search**. 1. Uncheck **Elasticsearch indexing** and **Search with Elasticsearch enabled**. 1. Select **Save changes**. @@ -308,7 +308,7 @@ To disable the Elasticsearch integration: ## Unpause Indexing -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > Advanced Search**. 1. Expand **Advanced Search**. 1. Clear the **Pause Elasticsearch indexing** checkbox. @@ -331,7 +331,7 @@ index alias to it which becomes the new `primary` index. At the end, we resume t To trigger the reindexing process: 1. Sign in to your GitLab instance as an administrator. -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > Advanced Search**. 1. Expand **Elasticsearch zero-downtime reindexing**. 1. Select **Trigger cluster reindexing**. @@ -348,7 +348,7 @@ While the reindexing is running, you can follow its progress under that same sec > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55681) in GitLab 13.12. -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > Advanced Search**. 1. Expand **Elasticsearch zero-downtime reindexing**, and you'll find the following options: @@ -396,7 +396,7 @@ Sometimes, you might want to abandon the unfinished reindex job and resume the i bundle exec rake gitlab:elastic:mark_reindex_failed RAILS_ENV=production ``` -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > Advanced Search**. 1. Expand **Advanced Search**. 1. Clear the **Pause Elasticsearch indexing** checkbox. @@ -562,7 +562,7 @@ For basic guidance on choosing a cluster configuration you may refer to [Elastic - A good guideline is to ensure you keep the number of shards per node below 20 per GB heap it has configured. A node with a 30GB heap should therefore have a maximum of 600 shards, but the further below this limit you can keep it the better. This generally helps the cluster stay in good health. - Number of Elasticsearch shards: - Small shards result in small segments, which increases overhead. Aim to keep the average shard size between at least a few GB and a few tens of GB. - - Another consideration is the number of documents. To determine the number of shards to use, sum the numbers in the **Menu > Admin > Dashboard > Statistics** pane (the number of documents to be indexed), divide by 5 million, and add 5. For example: + - Another consideration is the number of documents. To determine the number of shards to use, sum the numbers in the **Main menu > Admin > Dashboard > Statistics** pane (the number of documents to be indexed), divide by 5 million, and add 5. For example: - If you have fewer than about 2,000,000 documents, use the default of 5 shards - 10,000,000 documents: `10000000/5000000 + 5` = 7 shards - 100,000,000 documents: `100000000/5000000 + 5` = 25 shards @@ -639,7 +639,7 @@ Make sure to prepare for this task by having a ``` This enqueues a Sidekiq job for each project that needs to be indexed. - You can view the jobs in **Menu > Admin > Monitoring > Background Jobs > Queues Tab** + You can view the jobs in **Main menu > Admin > Monitoring > Background Jobs > Queues Tab** and select `elastic_commit_indexer`, or you can query indexing status using a Rake task: ```shell diff --git a/doc/integration/akismet.md b/doc/integration/akismet.md index b322e603a3c..a2b70d42bb6 100644 --- a/doc/integration/akismet.md +++ b/doc/integration/akismet.md @@ -30,7 +30,7 @@ To use Akismet: 1. Sign in or create a new account. 1. Select **Show** to reveal the API key, and copy the API key's value. 1. Sign in to GitLab as an administrator. -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > Reporting** (`/admin/application_settings/reporting`). 1. Select the **Enable Akismet** checkbox. 1. Fill in the API key from step 3. diff --git a/doc/integration/datadog.md b/doc/integration/datadog.md index b8624545c41..42337006189 100644 --- a/doc/integration/datadog.md +++ b/doc/integration/datadog.md @@ -27,7 +27,7 @@ project, group, or instance level: 1. *For project-level or group-level integrations:* In GitLab, go to your project or group. 1. *For instance-level integrations:* 1. Sign in to GitLab as a user with administrator access. - 1. On the top bar, select **Menu > Admin**. + 1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > Integrations**. 1. Scroll to **Add an integration**, and select **Datadog**. 1. Select **Active** to enable the integration. diff --git a/doc/integration/gitpod.md b/doc/integration/gitpod.md index 271505d3d6f..c2b27e79d6e 100644 --- a/doc/integration/gitpod.md +++ b/doc/integration/gitpod.md @@ -47,7 +47,7 @@ For GitLab self-managed instances, a GitLab administrator needs to: 1. Set up a Gitpod instance to integrate with GitLab. Refer to the [Gitpod documentation](https://www.gitpod.io/docs/self-hosted/latest) to get your instance up and running. 1. Enable it in GitLab: - 1. On the top bar, select **Menu > Admin**. + 1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > General**. 1. Expand the **Gitpod** configuration section. 1. Select the **Enable Gitpod integration** checkbox. diff --git a/doc/integration/jenkins.md b/doc/integration/jenkins.md index e174e02546a..0a4c2c27c31 100644 --- a/doc/integration/jenkins.md +++ b/doc/integration/jenkins.md @@ -128,7 +128,7 @@ Configure the GitLab integration with Jenkins in one of the following ways. GitLab recommends this approach for Jenkins integrations because it is easier to configure than the [webhook integration](#configure-a-webhook). -1. On the top bar, select **Menu > Projects** and find your project. +1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Settings > Integrations**. 1. Select **Jenkins**. 1. Select the **Active** checkbox. diff --git a/doc/integration/jira/configure.md b/doc/integration/jira/configure.md index bfeac230f89..58789afff46 100644 --- a/doc/integration/jira/configure.md +++ b/doc/integration/jira/configure.md @@ -22,7 +22,7 @@ Prerequisites: To configure your project: -1. On the top bar, select **Menu > Projects** and find your project. +1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Settings > Integrations**. 1. Select **Jira**. 1. Select **Enable integration**. diff --git a/doc/integration/jira/dvcs.md b/doc/integration/jira/dvcs.md index d22b606fa1d..ce097a4db23 100644 --- a/doc/integration/jira/dvcs.md +++ b/doc/integration/jira/dvcs.md @@ -277,7 +277,7 @@ In the example above, the merge requests feature is disabled. To resolve the issue, enable the relevant feature: -1. On the top bar, select **Menu > Projects** and find your project. +1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Settings > General**. 1. Expand **Visibility, project features, permissions**. 1. Use the toggles to enable the features as needed. diff --git a/doc/integration/jira/issues.md b/doc/integration/jira/issues.md index a0b102eb21f..98dd4526fd9 100644 --- a/doc/integration/jira/issues.md +++ b/doc/integration/jira/issues.md @@ -54,7 +54,7 @@ You can [disable comments](#disable-comments-on-jira-issues) on issues. You can prevent merge requests from being merged if they do not refer to a Jira issue. To enforce this: -1. On the top bar, select **Menu > Projects** and find your project. +1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Settings > Merge requests**. 1. In the **Merge checks** section, select **Require an associated issue from Jira**. 1. Select **Save**. diff --git a/doc/integration/kerberos.md b/doc/integration/kerberos.md index da854582c12..cff29189464 100644 --- a/doc/integration/kerberos.md +++ b/doc/integration/kerberos.md @@ -113,7 +113,7 @@ set up GitLab to create a new account when a Kerberos user tries to sign in. If you're an administrator, you can link a Kerberos account to an existing GitLab account. To do so: -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Overview > Users**. 1. Select a user, then select the **Identities** tab. 1. Select 'Kerberos SPNEGO' in the 'Provider' dropdown box. @@ -153,7 +153,7 @@ With that information at hand: ``` 1. As an administrator, you can confirm the new, blocked account: - 1. On the top bar, select **Menu > Admin**. + 1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Overview > Users** and review the **Blocked** tab. 1. You can enable the user. 1. If `block_auto_created_users` is false, the Kerberos user is diff --git a/doc/integration/oauth_provider.md b/doc/integration/oauth_provider.md index 962f5c4e5fb..d04baa1dc05 100644 --- a/doc/integration/oauth_provider.md +++ b/doc/integration/oauth_provider.md @@ -79,7 +79,7 @@ To add a new application for a group: To create an application for your GitLab instance: -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Applications**. 1. Select **New application**. diff --git a/doc/integration/omniauth.md b/doc/integration/omniauth.md index b74203f61a9..0dfc78b508b 100644 --- a/doc/integration/omniauth.md +++ b/doc/integration/omniauth.md @@ -195,7 +195,7 @@ By default, sign-in is enabled for all the OAuth providers configured in `config To enable or disable an OmniAuth provider: -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings**. 1. Expand **Sign-in restrictions**. 1. In the **Enabled OAuth authentication sources** section, select or clear the checkbox for each provider you want to enable or disable. diff --git a/doc/integration/recaptcha.md b/doc/integration/recaptcha.md index 9dcdb2064db..a5fd8db63bd 100644 --- a/doc/integration/recaptcha.md +++ b/doc/integration/recaptcha.md @@ -17,7 +17,7 @@ To use reCAPTCHA, first create a site and private key. 1. Go to the [Google reCAPTCHA page](https://www.google.com/recaptcha/admin). 1. To get reCAPTCHA v2 keys, fill in the form and select **Submit**. 1. Sign in to your GitLab server as an administrator. -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > Reporting** (`admin/application_settings/reporting`). 1. Expand **Spam and Anti-bot Protection**. 1. In the reCAPTCHA fields, enter the keys you obtained in the previous steps. diff --git a/doc/integration/sourcegraph.md b/doc/integration/sourcegraph.md index 72ad0bcc32d..731c21c17fa 100644 --- a/doc/integration/sourcegraph.md +++ b/doc/integration/sourcegraph.md @@ -49,7 +49,7 @@ You can skip this step if you already have your GitLab repositories searchable i ### Configure your GitLab instance with Sourcegraph -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > General**. 1. Expand the **Sourcegraph** configuration section. 1. Check **Enable Sourcegraph**. diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md index 35c3cd32a1f..03413aca2af 100644 --- a/doc/raketasks/backup_restore.md +++ b/doc/raketasks/backup_restore.md @@ -79,10 +79,18 @@ For detailed information on restoring GitLab, see [Restore GitLab](restore_gitla ## Alternative backup strategies -If your GitLab instance contains a lot of Git repository data, you may find the -GitLab backup script to be too slow. If your GitLab instance has a lot of forked -projects, the regular backup task also duplicates the Git data for all of them. -In these cases, consider using file system snapshots as part of your backup strategy. +In the following cases, consider using file system data transfer or snapshots as part of your backup strategy: + +- Your GitLab instance contains a lot of Git repository data and the GitLab backup script is too slow. +- Your GitLab instance has a lot of forked projects and the regular backup task duplicates the Git data for all of them. +- Your GitLab instance has a problem and using the regular backup and import Rake tasks isn't possible. + +When considering using file system data transfer or snapshots: + +- Don't use these methods to migrate from one operating system to another. The operating systems of the source and destination should be as similar as possible. For example, + don't use these methods to migrate from Ubuntu to Fedora. +- Data consistency is very important. We recommend stopping GitLab with `sudo gitlab-ctl stop` before taking doing a file system transfer (with rsync, for example) or taking a + snapshot. Example: Amazon Elastic Block Store (EBS) diff --git a/doc/subscriptions/gitlab_com/index.md b/doc/subscriptions/gitlab_com/index.md index 2e547a16f5e..aed8bafb780 100644 --- a/doc/subscriptions/gitlab_com/index.md +++ b/doc/subscriptions/gitlab_com/index.md @@ -48,7 +48,7 @@ Prerequisite: To see the status of your GitLab SaaS subscription: -1. On the top bar, select **Menu > Groups** and find your group. +1. On the top bar, select **Main menu > Groups** and find your group. 1. On the left sidebar, select **Settings > Billing**. The following information is displayed: @@ -98,7 +98,7 @@ In this case, they would see only the features available to that subscription. To view a list of seats being used: -1. On the top bar, select **Menu > Groups** and find your group. +1. On the top bar, select **Main menu > Groups** and find your group. 1. On the left sidebar, select **Settings > Usage Quotas**. 1. On the **Seats** tab, view usage information. @@ -128,7 +128,7 @@ For example: To export seat usage data as a CSV file: -1. On the top bar, select **Menu > Groups** and find your group. +1. On the top bar, select **Main menu > Groups** and find your group. 1. On the left sidebar, select **Settings > Billing**. 1. Under **Seats currently in use**, select **See usage**. 1. Select **Export list**. @@ -179,7 +179,7 @@ The following is emailed to you: To remove a billable user from your subscription: -1. On the top bar, select **Menu > Groups** and find your group. +1. On the top bar, select **Main menu > Groups** and find your group. 1. On the left sidebar, select **Settings > Billing**. 1. In the **Seats currently in use** section, select **See usage**. 1. In the row for the user you want to remove, on the right side, select the ellipsis and **Remove user**. @@ -346,7 +346,7 @@ main quota. You can find pricing for additional storage on the To purchase additional storage for your group on GitLab SaaS: -1. On the top bar, select **Menu > Groups** and find your group. +1. On the top bar, select **Main menu > Groups** and find your group. 1. On the left sidebar, select **Settings > Usage Quotas**. 1. Select **Storage** tab. 1. Select **Purchase more storage**. diff --git a/doc/subscriptions/index.md b/doc/subscriptions/index.md index 27194f43b53..e71954f1968 100644 --- a/doc/subscriptions/index.md +++ b/doc/subscriptions/index.md @@ -194,7 +194,7 @@ GitLab for Open Source Program benefits apply to an entire GitLab namespace. To To add a license: -1. On the top bar, select **Menu > Projects** and find your project. +1. On the top bar, select **Main menu > Projects** and find your project. 1. On the overview page, select **Add LICENSE**. If the license you want is not available as a license template, manually copy the entire, unaltered [text of your chosen license](https://opensource.org/licenses/alphabetical) into the `LICENSE` file. Note that GitLab defaults to **All rights reserved** if users do not perform this action. Applicants must add the correct license to each project in their respective groups or namespaces When you're sure you're using OSI-approved licenses for your projects, you can take your screenshots. @@ -211,7 +211,7 @@ Benefits of the GitLab Open Source Program apply to all projects in a GitLab nam ##### Screenshot 1: License overview -1. On the top bar, select **Menu > Projects** and find your project. +1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select your project avatar. If you haven't specified an avatar for your project, the avatar displays as a single letter. 1. Take a screenshot of the project overview that clearly displays the license you've chosen for your project. @@ -219,7 +219,7 @@ Benefits of the GitLab Open Source Program apply to all projects in a GitLab nam ##### Screenshot 2: License contents -1. On the top bar, select **Menu > Projects** and find your project. +1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Repository** and locate the project's `LICENSE` file. 1. Take a screenshot of the contents of the file. Make sure the screenshot includes the title of the license. @@ -229,7 +229,7 @@ Benefits of the GitLab Open Source Program apply to all projects in a GitLab nam To be eligible for the GitLab Open Source Program, projects must be publicly visible. To check your project's public visibility settings: -1. On the top bar, select **Menu > Projects** and find your project. +1. On the top bar, select **Main menu > Projects** and find your project. 1. From the left sidebar, select **Settings > General**. 1. Expand **Visibility, project features, permissions**. 1. From the **Project visibility** dropdown list, select **Public**. diff --git a/doc/subscriptions/self_managed/index.md b/doc/subscriptions/self_managed/index.md index 758b472d67b..4ae38de54bc 100644 --- a/doc/subscriptions/self_managed/index.md +++ b/doc/subscriptions/self_managed/index.md @@ -49,7 +49,7 @@ Prorated charges are not possible without a quarterly usage report. You can view users for your license and determine if you've gone over your subscription. -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left menu, select **Subscription**. The lists of users are displayed. @@ -218,7 +218,7 @@ to IP address `104.18.26.123:443` (`customers.gitlab.com`). You can manually sync your subscription details at any time. -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Subscription**. 1. In the **Subscription details** section, select **Sync subscription details**. @@ -241,7 +241,7 @@ instance, ensure you're purchasing enough seats to If you are an administrator, you can view the status of your subscription: -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Subscription**. The **Subscription** page includes the following details: @@ -265,7 +265,7 @@ It also displays the following information: If you are an administrator, you can export your license usage into a CSV: -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Subscription**. 1. In the top right, select **Export license usage file**. diff --git a/doc/user/application_security/container_scanning/index.md b/doc/user/application_security/container_scanning/index.md index 7963f0ce03e..961ccf6b563 100644 --- a/doc/user/application_security/container_scanning/index.md +++ b/doc/user/application_security/container_scanning/index.md @@ -1,7 +1,7 @@ --- type: reference, howto -stage: Protect -group: Container Security +stage: Secure +group: Composition Analysis info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- diff --git a/doc/user/application_security/cve_id_request.md b/doc/user/application_security/cve_id_request.md index 5ffd47527c5..6f076bbe3f9 100644 --- a/doc/user/application_security/cve_id_request.md +++ b/doc/user/application_security/cve_id_request.md @@ -1,6 +1,6 @@ --- type: tutorial -stage: Secure +stage: Govern group: Threat Insights info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- diff --git a/doc/user/application_security/generate_test_vulnerabilities/index.md b/doc/user/application_security/generate_test_vulnerabilities/index.md index aafbebb91cd..4d424acf9c3 100644 --- a/doc/user/application_security/generate_test_vulnerabilities/index.md +++ b/doc/user/application_security/generate_test_vulnerabilities/index.md @@ -1,6 +1,6 @@ --- type: reference, howto -stage: Secure +stage: Govern group: Threat Insights info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- diff --git a/doc/user/application_security/policies/index.md b/doc/user/application_security/policies/index.md index 61694a53813..9b86ef7316a 100644 --- a/doc/user/application_security/policies/index.md +++ b/doc/user/application_security/policies/index.md @@ -1,6 +1,6 @@ --- -stage: Protect -group: Container Security +stage: Govern +group: Security Policies info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- diff --git a/doc/user/application_security/policies/scan-execution-policies.md b/doc/user/application_security/policies/scan-execution-policies.md index 8f77f7598e9..f2fc52a2de8 100644 --- a/doc/user/application_security/policies/scan-execution-policies.md +++ b/doc/user/application_security/policies/scan-execution-policies.md @@ -1,6 +1,6 @@ --- -stage: Protect -group: Container Security +stage: Govern +group: Security Policies info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- diff --git a/doc/user/application_security/policies/scan-result-policies.md b/doc/user/application_security/policies/scan-result-policies.md index 3eee4957e2f..78a97b36e92 100644 --- a/doc/user/application_security/policies/scan-result-policies.md +++ b/doc/user/application_security/policies/scan-result-policies.md @@ -1,6 +1,6 @@ --- -stage: Protect -group: Container Security +stage: Govern +group: Security Policies info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- diff --git a/doc/user/application_security/security_dashboard/index.md b/doc/user/application_security/security_dashboard/index.md index c5dfa1af302..1cf605c16bb 100644 --- a/doc/user/application_security/security_dashboard/index.md +++ b/doc/user/application_security/security_dashboard/index.md @@ -1,6 +1,6 @@ --- type: reference, howto -stage: Secure +stage: Govern group: Threat Insights info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- diff --git a/doc/user/application_security/vulnerabilities/index.md b/doc/user/application_security/vulnerabilities/index.md index 02bcda2c28e..91793272cce 100644 --- a/doc/user/application_security/vulnerabilities/index.md +++ b/doc/user/application_security/vulnerabilities/index.md @@ -1,5 +1,5 @@ --- -stage: Secure +stage: Govern group: Threat Insights info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- diff --git a/doc/user/application_security/vulnerabilities/severities.md b/doc/user/application_security/vulnerabilities/severities.md index 987dac677e7..aed86cd93aa 100644 --- a/doc/user/application_security/vulnerabilities/severities.md +++ b/doc/user/application_security/vulnerabilities/severities.md @@ -1,6 +1,6 @@ --- type: reference -stage: Secure +stage: Govern group: Threat Insights info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- diff --git a/doc/user/application_security/vulnerability_report/index.md b/doc/user/application_security/vulnerability_report/index.md index 4b688519916..ba448d410ea 100644 --- a/doc/user/application_security/vulnerability_report/index.md +++ b/doc/user/application_security/vulnerability_report/index.md @@ -1,6 +1,6 @@ --- type: reference, howto -stage: Secure +stage: Govern group: Threat Insights info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- diff --git a/doc/user/application_security/vulnerability_report/pipeline.md b/doc/user/application_security/vulnerability_report/pipeline.md index 0c05fd27b6a..7faf273515c 100644 --- a/doc/user/application_security/vulnerability_report/pipeline.md +++ b/doc/user/application_security/vulnerability_report/pipeline.md @@ -1,6 +1,6 @@ --- type: reference, howto -stage: Secure +stage: Govern group: Threat Insights info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- diff --git a/doc/user/compliance/compliance_report/index.md b/doc/user/compliance/compliance_report/index.md index 4cd2705e917..e623e906971 100644 --- a/doc/user/compliance/compliance_report/index.md +++ b/doc/user/compliance/compliance_report/index.md @@ -1,6 +1,6 @@ --- type: reference, howto -stage: Manage +stage: Govern group: Compliance info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- diff --git a/doc/user/compliance/index.md b/doc/user/compliance/index.md index 7b46886e236..c6c4834228b 100644 --- a/doc/user/compliance/index.md +++ b/doc/user/compliance/index.md @@ -1,6 +1,6 @@ --- type: reference -stage: Manage +stage: Govern group: Compliance info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- diff --git a/doc/user/packages/harbor_container_registry/index.md b/doc/user/packages/harbor_container_registry/index.md new file mode 100644 index 00000000000..12c61d9d12c --- /dev/null +++ b/doc/user/packages/harbor_container_registry/index.md @@ -0,0 +1,69 @@ +--- +stage: Package +group: Package +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +--- + +# Harbor Registry **(FREE)** + +You can integrate the [Harbor container registry](../../../user/project/integrations/harbor.md#harbor-container-registry-integration) into GitLab and use Harbor as the container registry for your GitLab project to store images. + +## View the Harbor Registry + +You can view the Harbor Registry for a project or group. + +1. On the top bar, select **Menu > Projects/Groups**. +1. Go to the project or group that you are interested in. +1. On the left sidebar, select **Packages and registries > Harbor Registry**. + +You can search, sort, and filter images on this page. You can share a filtered view by copying the URL from your browser. + +At the project level, you can see **CLI Commands** in the upper right corner, where you can copy +corresponding commands to log in, build images, and push images. **CLI Commands** is not shown at +the group level. + +NOTE: +Default settings for the Harbor integration at the project level are inherited from the group level. + +## Use images from the Harbor Registry + +To download and run a Harbor image hosted in the GitLab Harbor Registry: + +1. Copy the link to your container image: + 1. Go to your project or group's **Packages and registries > Harbor Registry** and find the image you want. + 1. Click the **Copy** icon next to the image name. + +1. Use the command to run the container image you want. + +## View the tags of a specific artifact + +To view the list of tags associated with a specific artifact: + +1. Go to your project or group. +1. Go to **Packages and registries > Harbor Registry**. +1. Click the image name to view its artifacts. +1. Select the artifact you want. + +This brings up the list of tags. You can view the tag count and the time published. + +You can also copy the tag URL and use it to pull the corresponding artifact. + +## Build and push images by using commands + +To build and push to the Harbor Registry: + +1. Authenticate with the Harbor Registry. +1. Run the command to build or push. + +To view these commands, go to your project's **Packages and registries > Harbor Registry > CLI Commands**. + +## Disable the Harbor Registry for a project + +To remove the Harbor Registry for a project: + +1. Go to your project/group's **Settings > Integrations** page. +1. Click **Harbor** under **Active integrations**. +1. Clear the **Active** checkbox under **Enable integration**. +1. Select **Save changes**. + +The **Packages and registries > Harbor Registry** entry is removed from the sidebar. diff --git a/doc/user/project/integrations/asana.md b/doc/user/project/integrations/asana.md index a10e261f10e..07b37b5be43 100644 --- a/doc/user/project/integrations/asana.md +++ b/doc/user/project/integrations/asana.md @@ -32,7 +32,7 @@ In Asana, create a Personal Access Token. Complete these steps in GitLab: -1. On the top bar, select **Menu > Projects** and find your project. +1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Settings > Integrations**. 1. Select **Asana**. 1. Ensure that the **Active** toggle is enabled. diff --git a/doc/user/project/integrations/bamboo.md b/doc/user/project/integrations/bamboo.md index 75f099268cb..7b39f6c7162 100644 --- a/doc/user/project/integrations/bamboo.md +++ b/doc/user/project/integrations/bamboo.md @@ -36,7 +36,7 @@ integration in GitLab. ## Configure GitLab -1. On the top bar, select **Menu > Projects** and find your project. +1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Settings > Integrations**. 1. Select **Atlassian Bamboo**. 1. Ensure the **Active** checkbox is selected. diff --git a/doc/user/project/integrations/bugzilla.md b/doc/user/project/integrations/bugzilla.md index ac4b9d0769b..f058950e0f4 100644 --- a/doc/user/project/integrations/bugzilla.md +++ b/doc/user/project/integrations/bugzilla.md @@ -14,7 +14,7 @@ You can configure Bugzilla as an To enable the Bugzilla integration in a project: -1. On the top bar, select **Menu > Projects** and find your project. +1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Settings > Integrations**. 1. Select **Bugzilla**. 1. Select the checkbox under **Enable integration**. diff --git a/doc/user/project/integrations/custom_issue_tracker.md b/doc/user/project/integrations/custom_issue_tracker.md index 71ca9f4f640..c3794aa1a2b 100644 --- a/doc/user/project/integrations/custom_issue_tracker.md +++ b/doc/user/project/integrations/custom_issue_tracker.md @@ -20,7 +20,7 @@ on the left sidebar in your project. To enable a custom issue tracker in a project: -1. On the top bar, select **Menu > Projects** and find your project. +1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Settings > Integrations**. 1. Select **Custom issue tracker**. 1. Select the checkbox under **Enable integration**. diff --git a/doc/user/project/integrations/discord_notifications.md b/doc/user/project/integrations/discord_notifications.md index 3780ea37c0b..dffcc780206 100644 --- a/doc/user/project/integrations/discord_notifications.md +++ b/doc/user/project/integrations/discord_notifications.md @@ -26,7 +26,7 @@ and configure it in GitLab. With the webhook URL created in the Discord channel, you can set up the Discord Notifications service in GitLab. -1. On the top bar, select **Menu > Projects** and find your project. +1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Settings > Integrations**. 1. Select **Discord Notifications**. 1. Ensure that the **Active** toggle is enabled. diff --git a/doc/user/project/integrations/emails_on_push.md b/doc/user/project/integrations/emails_on_push.md index c1c48c7fb12..37d9a86f8fa 100644 --- a/doc/user/project/integrations/emails_on_push.md +++ b/doc/user/project/integrations/emails_on_push.md @@ -11,7 +11,7 @@ that is pushed to your project. To enable emails on push: -1. On the top bar, select **Menu > Projects** and find your project. +1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Settings > Integrations**. 1. Select **Emails on push**. 1. In the **Recipients** section, provide a list of emails separated by spaces or newlines. diff --git a/doc/user/project/integrations/ewm.md b/doc/user/project/integrations/ewm.md index b02f1a06e96..45f3653757d 100644 --- a/doc/user/project/integrations/ewm.md +++ b/doc/user/project/integrations/ewm.md @@ -14,7 +14,7 @@ This IBM product was [formerly named Rational Team Concert](https://jazz.net/blo To enable the EWM integration, in a project: -1. On the top bar, select **Menu > Projects** and find your project. +1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Settings > Integrations**. 1. Select **EWM**. 1. Select the checkbox under **Enable integration**. diff --git a/doc/user/project/integrations/github.md b/doc/user/project/integrations/github.md index d53b892281f..4be541d99cb 100644 --- a/doc/user/project/integrations/github.md +++ b/doc/user/project/integrations/github.md @@ -29,7 +29,7 @@ Complete these steps on GitHub: Complete these steps in GitLab: -1. On the top bar, select **Menu > Projects** and find your project. +1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Settings > Integrations**. 1. Select **GitHub**. 1. Ensure the **Active** checkbox is selected. diff --git a/doc/user/project/integrations/harbor.md b/doc/user/project/integrations/harbor.md index 8fe9b7fc9ff..535703ff59e 100644 --- a/doc/user/project/integrations/harbor.md +++ b/doc/user/project/integrations/harbor.md @@ -25,7 +25,7 @@ In the Harbor instance, ensure that: GitLab supports integrating Harbor projects at the group or project level. Complete these steps in GitLab: -1. On the top bar, select **Menu > Projects** and find your project. +1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Settings > Integrations**. 1. Select **Harbor**. 1. Turn on the **Active** toggle under **Enable Integration**. diff --git a/doc/user/project/integrations/index.md b/doc/user/project/integrations/index.md index 4ff42fe9acc..18e827f8df8 100644 --- a/doc/user/project/integrations/index.md +++ b/doc/user/project/integrations/index.md @@ -18,7 +18,7 @@ Prerequisites: To view the available integrations for your project: -1. On the top bar, select **Menu > Projects** and find your project. +1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Settings > Integrations**. You can also view and manage integration settings across [all projects in an instance or group](../../admin_area/settings/project_integration_management.md). diff --git a/doc/user/project/integrations/irker.md b/doc/user/project/integrations/irker.md index b2c2aea2c2b..5f7de09cc9d 100644 --- a/doc/user/project/integrations/irker.md +++ b/doc/user/project/integrations/irker.md @@ -39,7 +39,7 @@ network. For more details, read ## Complete these steps in GitLab -1. On the top bar, select **Menu > Projects** and find your project. +1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Settings > Integrations**. 1. Select **irker (IRC gateway)**. 1. Ensure that the **Active** toggle is enabled. diff --git a/doc/user/project/integrations/mattermost.md b/doc/user/project/integrations/mattermost.md index 7dd4c1d1a8b..12575e34058 100644 --- a/doc/user/project/integrations/mattermost.md +++ b/doc/user/project/integrations/mattermost.md @@ -39,7 +39,7 @@ Display name override is not enabled by default, you need to ask your administra After the Mattermost instance has an incoming webhook set up, you can set up GitLab to send the notifications: -1. On the top bar, select **Menu > Projects** and find your project. +1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Settings > Integrations**. 1. Select **Mattermost notifications**. 1. Select the GitLab events to generate notifications for. For each event you select, input the Mattermost channel diff --git a/doc/user/project/integrations/mattermost_slash_commands.md b/doc/user/project/integrations/mattermost_slash_commands.md index 9335854133f..28a5f2eec18 100644 --- a/doc/user/project/integrations/mattermost_slash_commands.md +++ b/doc/user/project/integrations/mattermost_slash_commands.md @@ -29,7 +29,7 @@ you must have Mattermost [3.4 or later](https://mattermost.com/blog/category/pla If Mattermost is installed on the same server as GitLab, you can automatically configure Mattermost slash commands: -1. On the top bar, select **Menu > Projects** and find your project. +1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Settings > Integrations**. 1. In **Add an integration**, select **Mattermost slash commands**. 1. In **Enable integration**, ensure the **Active** checkbox is selected. @@ -65,7 +65,7 @@ To get configuration values from GitLab: 1. In a different browser tab, sign in to GitLab as a user with administrator access. -1. On the top bar, select **Menu > Admin**. +1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > Integrations**. 1. Select **Mattermost slash commands**. GitLab displays potential values for Mattermost settings. 1. Copy the **Request URL** value. All other values are suggestions. diff --git a/doc/user/project/integrations/microsoft_teams.md b/doc/user/project/integrations/microsoft_teams.md index 6679bab745b..2e6954390fb 100644 --- a/doc/user/project/integrations/microsoft_teams.md +++ b/doc/user/project/integrations/microsoft_teams.md @@ -35,7 +35,7 @@ After you configure Microsoft Teams to receive notifications, you must configure GitLab to send the notifications: 1. Sign in to GitLab as an administrator. -1. On the top bar, select **Menu > Projects** and find your project. +1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Settings > Integrations**. 1. Select **Microsoft Teams notifications**. 1. To enable the integration, select **Active**. diff --git a/doc/user/project/integrations/pivotal_tracker.md b/doc/user/project/integrations/pivotal_tracker.md index 7f5414b86de..a0798da21f0 100644 --- a/doc/user/project/integrations/pivotal_tracker.md +++ b/doc/user/project/integrations/pivotal_tracker.md @@ -37,7 +37,7 @@ In Pivotal Tracker, [create an API token](https://www.pivotaltracker.com/help/ar Complete these steps in GitLab: -1. On the top bar, select **Menu > Projects** and find your project. +1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Settings > Integrations**. 1. Select **Pivotal Tracker**. 1. Ensure that the **Active** toggle is enabled. diff --git a/doc/user/project/integrations/prometheus.md b/doc/user/project/integrations/prometheus.md index 068a2810a53..c1181169261 100644 --- a/doc/user/project/integrations/prometheus.md +++ b/doc/user/project/integrations/prometheus.md @@ -62,7 +62,7 @@ GitLab can use these to access the resource. More information about authenticati service account can be found at Google's documentation for [Authenticating from a service account](https://cloud.google.com/iap/docs/authentication-howto#authenticating_from_a_service_account). -1. On the top bar, select **Menu > Projects** and find your project. +1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Settings > Integrations**. 1. Select **Prometheus**. 1. For **API URL**, provide the domain name or IP address of your server, such as @@ -83,7 +83,7 @@ You can configure [Thanos](https://thanos.io/) as a drop-in replacement for Prom with GitLab. Use the domain name or IP address of the Thanos server you'd like to integrate with. -1. On the top bar, select **Menu > Projects** and find your project. +1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Settings > Integrations**. 1. Select **Prometheus**. 1. Provide the domain name or IP address of your server, for example diff --git a/doc/user/project/integrations/pumble.md b/doc/user/project/integrations/pumble.md index 4d22fdd3fb9..0eb3a38bb86 100644 --- a/doc/user/project/integrations/pumble.md +++ b/doc/user/project/integrations/pumble.md @@ -26,7 +26,7 @@ notifications: 1. To enable the integration for your group or project: 1. In your group or project, on the left sidebar, select **Settings > Integrations**. 1. To enable the integration for your instance: - 1. On the top bar, select **Menu > Admin**. + 1. On the top bar, select **Main menu > Admin**. 1. On the left sidebar, select **Settings > Integrations**. 1. Select the **Pumble** integration. 1. Ensure that the **Active** toggle is enabled. diff --git a/doc/user/project/integrations/redmine.md b/doc/user/project/integrations/redmine.md index a989b418199..bc1d299dccf 100644 --- a/doc/user/project/integrations/redmine.md +++ b/doc/user/project/integrations/redmine.md @@ -10,7 +10,7 @@ Use [Redmine](https://www.redmine.org/) as the issue tracker. To enable the Redmine integration in a project: -1. On the top bar, select **Menu > Projects** and find your project. +1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Settings > Integrations**. 1. Select **Redmine**. 1. Select the checkbox under **Enable integration**. diff --git a/doc/user/project/integrations/slack.md b/doc/user/project/integrations/slack.md index dd0f57570aa..ae2e57a6d7f 100644 --- a/doc/user/project/integrations/slack.md +++ b/doc/user/project/integrations/slack.md @@ -22,7 +22,7 @@ to control GitLab from Slack. Slash commands are configured separately. ## Configure GitLab -1. On the top bar, select **Menu > Projects** and find your project. +1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Settings > Integrations**. 1. Select **Slack notifications**. 1. In the **Enable integration** section, select the **Active** checkbox. diff --git a/doc/user/project/integrations/slack_slash_commands.md b/doc/user/project/integrations/slack_slash_commands.md index 5ad344a7d8e..67d6befb5fc 100644 --- a/doc/user/project/integrations/slack_slash_commands.md +++ b/doc/user/project/integrations/slack_slash_commands.md @@ -21,7 +21,7 @@ For GitLab.com, use the [GitLab Slack app](gitlab_slack_application.md) instead. Slack slash command integrations are scoped to a project. -1. In GitLab, on the top bar, select **Menu > Projects** and find your project. +1. In GitLab, on the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Settings > Integrations**. 1. Select **Slack slash commands**. Leave this browser tab open. 1. Open a new browser tab, sign in to your Slack team, and [start a new Slash Commands integration](https://my.slack.com/services/new/slash-commands). diff --git a/doc/user/project/integrations/unify_circuit.md b/doc/user/project/integrations/unify_circuit.md index 1e607d89e80..91beefd30ab 100644 --- a/doc/user/project/integrations/unify_circuit.md +++ b/doc/user/project/integrations/unify_circuit.md @@ -15,7 +15,7 @@ copy its URL. In GitLab: -1. On the top bar, select **Menu > Projects** and find your project. +1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Settings > Integrations**. 1. Select **Unify Circuit**. 1. Turn on the **Active** toggle. diff --git a/doc/user/project/integrations/webex_teams.md b/doc/user/project/integrations/webex_teams.md index e8b2470cf13..0b487e29d26 100644 --- a/doc/user/project/integrations/webex_teams.md +++ b/doc/user/project/integrations/webex_teams.md @@ -27,7 +27,7 @@ notifications: 1. Navigate to: - **Settings > Integrations** in a project to enable the integration at the project level. - **Settings > Integrations** in a group to enable the integration at the group level. - - On the top bar, select **Menu > Admin**. Then, in the left sidebar, + - On the top bar, select **Main menu > Admin**. Then, in the left sidebar, select **Settings > Integrations** to enable an instance-level integration. 1. Select the **Webex Teams** integration. 1. Ensure that the **Active** toggle is enabled. diff --git a/doc/user/project/integrations/youtrack.md b/doc/user/project/integrations/youtrack.md index 25fc9c4e1c3..e6071e7517d 100644 --- a/doc/user/project/integrations/youtrack.md +++ b/doc/user/project/integrations/youtrack.md @@ -14,7 +14,7 @@ You can configure YouTrack as an To enable the YouTrack integration in a project: -1. On the top bar, select **Menu > Projects** and find your project. +1. On the top bar, select **Main menu > Projects** and find your project. 1. On the left sidebar, select **Settings > Integrations**. 1. Select **YouTrack**. 1. Select the checkbox under **Enable integration**. diff --git a/doc/user/project/merge_requests/csv_export.md b/doc/user/project/merge_requests/csv_export.md index 893b2bc6811..954687212e7 100644 --- a/doc/user/project/merge_requests/csv_export.md +++ b/doc/user/project/merge_requests/csv_export.md @@ -1,5 +1,5 @@ --- -stage: Manage +stage: Govern group: Compliance info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- diff --git a/doc/user/project/merge_requests/status_checks.md b/doc/user/project/merge_requests/status_checks.md index f6c55210419..da705a53153 100644 --- a/doc/user/project/merge_requests/status_checks.md +++ b/doc/user/project/merge_requests/status_checks.md @@ -1,5 +1,5 @@ --- -stage: Manage +stage: Govern group: Compliance info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments" type: reference, concepts diff --git a/lib/gitlab/jira_import.rb b/lib/gitlab/jira_import.rb index 60344e4be68..fd41d9eeb5a 100644 --- a/lib/gitlab/jira_import.rb +++ b/lib/gitlab/jira_import.rb @@ -66,11 +66,6 @@ module Gitlab cache_class.write(cache_key, value) end - def self.cache_issue_mapping(issue_id, jira_issue_id, project_id) - cache_key = JiraImport.jira_item_cache_key(project_id, jira_issue_id, :issues) - cache_class.write(cache_key, issue_id) - end - def self.get_import_label_id(project_id) cache_class.read(JiraImport.import_label_cache_key(project_id)) end diff --git a/lib/gitlab/subscription_portal.rb b/lib/gitlab/subscription_portal.rb index 7ef1be6ff44..7494f0584d0 100644 --- a/lib/gitlab/subscription_portal.rb +++ b/lib/gitlab/subscription_portal.rb @@ -22,6 +22,10 @@ module Gitlab "payment_method_validation" end + def self.registration_validation_form_id + "cc_registration_validation" + end + def self.registration_validation_form_url "#{self.subscriptions_url}/payment_forms/cc_registration_validation" end @@ -90,3 +94,4 @@ Gitlab::SubscriptionPortal::PAYMENT_FORM_URL = Gitlab::SubscriptionPortal.paymen Gitlab::SubscriptionPortal::PAYMENT_VALIDATION_FORM_ID = Gitlab::SubscriptionPortal.payment_validation_form_id.freeze Gitlab::SubscriptionPortal::RENEWAL_SERVICE_EMAIL = Gitlab::SubscriptionPortal.renewal_service_email.freeze Gitlab::SubscriptionPortal::REGISTRATION_VALIDATION_FORM_URL = Gitlab::SubscriptionPortal.registration_validation_form_url.freeze +Gitlab::SubscriptionPortal::REGISTRATION_VALIDATION_FORM_ID = Gitlab::SubscriptionPortal.registration_validation_form_id.freeze diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb index 9920b72aa52..e2232dc5e2a 100644 --- a/lib/gitlab/usage_data.rb +++ b/lib/gitlab/usage_data.rb @@ -268,7 +268,7 @@ module Gitlab # @return [Array<#totals>] An array of objects that respond to `#totals` def usage_data_counters - Gitlab::UsageDataCounters.counters + Gitlab::UsageDataCounters.unmigrated_counters end def components_usage_data diff --git a/lib/gitlab/usage_data_counters.rb b/lib/gitlab/usage_data_counters.rb index 224897ed758..27376b9d231 100644 --- a/lib/gitlab/usage_data_counters.rb +++ b/lib/gitlab/usage_data_counters.rb @@ -3,7 +3,6 @@ module Gitlab module UsageDataCounters COUNTERS = [ - PackageEventCounter, WikiPageCounter, WebIdeCounter, NoteCounter, @@ -20,12 +19,22 @@ module Gitlab MergeRequestWidgetExtensionCounter ].freeze + COUNTERS_MIGRATED_TO_INSTRUMENTATION_CLASSES = [ + PackageEventCounter + ].freeze + UsageDataCounterError = Class.new(StandardError) UnknownEvent = Class.new(UsageDataCounterError) class << self + def unmigrated_counters + # we are using the #counters method instead of the COUNTERS const + # to make sure it's working correctly for `ee` version of UsageDataCounters + counters - self::COUNTERS_MIGRATED_TO_INSTRUMENTATION_CLASSES + end + def counters - self::COUNTERS + self::COUNTERS + self::COUNTERS_MIGRATED_TO_INSTRUMENTATION_CLASSES end def count(event_name) diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 2b868335606..4ac41dba6da 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -6707,6 +6707,9 @@ msgstr "" msgid "Bold text" msgstr "" +msgid "Bot" +msgstr "" + msgid "Both SSH and HTTP(S)" msgstr "" @@ -19373,7 +19376,7 @@ msgstr "" msgid "HarborRegistry|To widen your search, change or remove the filters above." msgstr "" -msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}." +msgid "HarborRegistry|We are having trouble connecting to the Harbor Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the documentation%{docLinkEnd}." msgstr "" msgid "HarborRegistry|With the Harbor Registry, every project can connect to a harbor space to store its Docker images." @@ -19824,6 +19827,9 @@ msgstr "" msgid "IdentityVerification|For added security, you'll need to verify your identity. We've sent a verification code to %{email}" msgstr "" +msgid "IdentityVerification|GitLab will not charge or store your payment information, it will only be used for verification." +msgstr "" + msgid "IdentityVerification|Help us keep GitLab secure" msgstr "" @@ -19884,6 +19890,9 @@ msgstr "" msgid "IdentityVerification|Verify code" msgstr "" +msgid "IdentityVerification|Verify payment method" +msgstr "" + msgid "IdentityVerification|Verify your identity" msgstr "" @@ -21317,6 +21326,9 @@ msgstr "" msgid "Integrations|Add namespace" msgstr "" +msgid "Integrations|Adding a namespace only works in browsers that allow cross-site cookies. %{linkStart}Learn more%{linkEnd}." +msgstr "" + msgid "Integrations|All details" msgstr "" @@ -21377,12 +21389,18 @@ msgstr "" msgid "Integrations|Enable comments" msgstr "" +msgid "Integrations|Ensure your instance URL is correct and your instance is configured correctly. %{linkStart}Learn more%{linkEnd}." +msgstr "" + msgid "Integrations|Enter your alias" msgstr "" msgid "Integrations|Failed to link namespace. Please try again." msgstr "" +msgid "Integrations|Failed to load Jira Connect Application ID. Please try again." +msgstr "" + msgid "Integrations|Failed to load namespaces. Please try again." msgstr "" @@ -21395,6 +21413,9 @@ msgstr "" msgid "Integrations|Failed to unlink namespace. Please try again." msgstr "" +msgid "Integrations|Failed to update GitLab version. Please try again." +msgstr "" + msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}." msgstr "" @@ -32308,18 +32329,45 @@ msgstr "" msgid "PushRules|All committed filenames cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, any filename is allowed." msgstr "" +msgid "PushRules|Branch name" +msgstr "" + +msgid "PushRules|Check whether the commit author is a GitLab user" +msgstr "" + +msgid "PushRules|Commit author's email" +msgstr "" + msgid "PushRules|Commit messages cannot match this %{wiki_syntax_link_start}regular expression%{wiki_syntax_link_end}. If empty, commit messages are not rejected based on any expression." msgstr "" msgid "PushRules|Do not allow users to remove Git tags with %{code_block_start}git push%{code_block_end}" msgstr "" +msgid "PushRules|Maximum file size (MB)" +msgstr "" + +msgid "PushRules|Prevent pushing secret files" +msgstr "" + +msgid "PushRules|Prohibited file names" +msgstr "" + msgid "PushRules|Reject any files likely to contain secrets. %{secret_files_link_start}What secret files are rejected?%{secret_files_link_end}" msgstr "" +msgid "PushRules|Reject expression in commit messages" +msgstr "" + msgid "PushRules|Reject file sizes equal to or greater than this size. If set to 0, files of any size are allowed. This rule does not apply to files tracked by Git LFS." msgstr "" +msgid "PushRules|Reject unsigned commits" +msgstr "" + +msgid "PushRules|Require expression in commit messages" +msgstr "" + msgid "PushRules|Restrict commits to existing GitLab users." msgstr "" @@ -38486,7 +38534,13 @@ msgstr "" msgid "SuperSonics|Activation code" msgstr "" -msgid "SuperSonics|An error occurred while adding your subscription." +msgid "SuperSonics|Activation not possible due to seat mismatch" +msgstr "" + +msgid "SuperSonics|Activation not possible due to true-up value mismatch" +msgstr "" + +msgid "SuperSonics|An error occurred while adding your subscription" msgstr "" msgid "SuperSonics|Billable users" @@ -38495,7 +38549,7 @@ msgstr "" msgid "SuperSonics|Buy subscription" msgstr "" -msgid "SuperSonics|Cannot activate instance due to a connectivity issue." +msgid "SuperSonics|Cannot activate instance due to a connectivity issue" msgstr "" msgid "SuperSonics|Cloud licensing" @@ -38611,25 +38665,37 @@ msgstr "" msgid "SuperSonics|You have added a license that activates on %{date}. Please see the subscription history table below for more details." msgstr "" +msgid "SuperSonics|You have applied a true-up for %{trueUpQuantity} %{trueUpQuantityUsers} but you need one for %{expectedTrueUpQuantity} %{expectedTrueUpQuantityUsers}. To pay for seat overages, contact your sales representative. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}." +msgstr "" + msgid "SuperSonics|You have successfully added a license that activates on %{date}. Please see the subscription history table below for more details." msgstr "" +msgid "SuperSonics|You may have entered an expired or ineligible activation code. To request a new activation code, %{purchaseSubscriptionLinkStart}purchase a new subscription%{purchaseSubscriptionLinkEnd} or %{supportLinkStart}contact GitLab Support%{supportLinkEnd} for further assistance." +msgstr "" + msgid "SuperSonics|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement." msgstr "" msgid "SuperSonics|Your %{subscriptionEntryName} cannot be displayed at the moment. Please refresh the page to try again." msgstr "" +msgid "SuperSonics|Your current GitLab installation has %{userCount} active %{userCountUsers}, which exceeds your new subscription seat count of %{licenseUserCount} by %{overageCount}. To activate your new subscription, %{purchaseLinkStart}purchase%{purchaseLinkEnd} an additional %{overageCount} %{overageCountSeats}, or %{deactivateLinkStart}deactivate%{deactivateLinkEnd} or %{blockLinkStart}block%{blockLinkEnd} %{overageCount} %{overageCountUsers}. For further assistance, contact %{licenseSupportLinkStart}GitLab support%{licenseSupportLinkEnd}." +msgstr "" + msgid "SuperSonics|Your future dated license was successfully added" msgstr "" msgid "SuperSonics|Your subscription" msgstr "" +msgid "SuperSonics|Your subscription cannot be located" +msgstr "" + msgid "SuperSonics|Your subscription details will sync shortly." msgstr "" -msgid "SuperSonics|Your subscription is expired." +msgid "SuperSonics|Your subscription is expired" msgstr "" msgid "SuperSonics|Your subscription was successfully activated. You can see the details below." @@ -47817,6 +47883,11 @@ msgstr "" msgid "scan-execution-policy: policy not applied, %{policy_path} file is missing" msgstr "" +msgid "seat" +msgid_plural "seats" +msgstr[0] "" +msgstr[1] "" + msgid "security Reports|There was an error creating the merge request" msgstr "" @@ -47991,6 +48062,11 @@ msgstr "" msgid "uploads" msgstr "" +msgid "user" +msgid_plural "users" +msgstr[0] "" +msgstr[1] "" + msgid "user avatar" msgstr "" diff --git a/spec/finders/merge_requests_finder_spec.rb b/spec/finders/merge_requests_finder_spec.rb index 0b6c438fd02..deeca6132e0 100644 --- a/spec/finders/merge_requests_finder_spec.rb +++ b/spec/finders/merge_requests_finder_spec.rb @@ -493,7 +493,7 @@ RSpec.describe MergeRequestsFinder do end end - context 'filtering by approved by' do + context 'filtering by approved by username' do let(:params) { { approved_by_usernames: user2.username } } before do @@ -506,6 +506,16 @@ RSpec.describe MergeRequestsFinder do expect(merge_requests).to contain_exactly(merge_request3) end + context 'with sorting by milestone' do + let(:params) { { approved_by_usernames: user2.username, sort: 'milestone' } } + + it 'returns merge requests approved by that user' do + merge_requests = described_class.new(user, params).execute + + expect(merge_requests).to contain_exactly(merge_request3) + end + end + context 'not filter' do let(:params) { { not: { approved_by_usernames: user2.username } } } @@ -531,6 +541,30 @@ RSpec.describe MergeRequestsFinder do end end + context 'filtering by approved by user ID' do + let(:params) { { approved_by_ids: user2.id } } + + before do + create(:approval, merge_request: merge_request3, user: user2) + end + + it 'returns merge requests approved by that user' do + merge_requests = described_class.new(user, params).execute + + expect(merge_requests).to contain_exactly(merge_request3) + end + + context 'with sorting by milestone' do + let(:params) { { approved_by_usernames: user2.username, sort: 'milestone' } } + + it 'returns merge requests approved by that user' do + merge_requests = described_class.new(user, params).execute + + expect(merge_requests).to contain_exactly(merge_request3) + end + end + end + context 'filtering by created_at/updated_at' do let(:new_project) { create(:project, forked_from_project: project1) } @@ -732,7 +766,8 @@ RSpec.describe MergeRequestsFinder do release_tag: 'none', label_names: 'none', my_reaction_emoji: 'none', - draft: 'no' + draft: 'no', + sort: 'milestone' } merge_requests = described_class.new(user, params).execute diff --git a/spec/frontend/jira_connect/subscriptions/api_spec.js b/spec/frontend/jira_connect/subscriptions/api_spec.js index 76a0b8fa82c..cf496d5836a 100644 --- a/spec/frontend/jira_connect/subscriptions/api_spec.js +++ b/spec/frontend/jira_connect/subscriptions/api_spec.js @@ -6,6 +6,7 @@ import { fetchGroups, getCurrentUser, addJiraConnectSubscription, + updateInstallation, } from '~/jira_connect/subscriptions/api'; import { getJwt } from '~/jira_connect/subscriptions/utils'; import httpStatus from '~/lib/utils/http_status'; @@ -153,4 +154,40 @@ describe('JiraConnect API', () => { expect(response.data).toEqual(mockResponse); }); }); + + describe('updateInstallation', () => { + const expectedUrl = '/-/jira_connect/installations'; + + it.each` + instanceUrl | expectedInstanceUrl + ${'https://gitlab.com'} | ${null} + ${'https://gitlab.mycompany.com'} | ${'https://gitlab.mycompany.com'} + `( + 'when instanceUrl is $instanceUrl, it passes `instance_url` as $expectedInstanceUrl', + async ({ instanceUrl, expectedInstanceUrl }) => { + const makeRequest = () => updateInstallation(instanceUrl); + + jest.spyOn(axiosInstance, 'put'); + axiosMock + .onPut(expectedUrl, { + jwt: mockJwt, + installation: { + instance_url: expectedInstanceUrl, + }, + }) + .replyOnce(httpStatus.OK, mockResponse); + + response = await makeRequest(); + + expect(getJwt).toHaveBeenCalled(); + expect(axiosInstance.put).toHaveBeenCalledWith(expectedUrl, { + jwt: mockJwt, + installation: { + instance_url: expectedInstanceUrl, + }, + }); + expect(response.data).toEqual(mockResponse); + }, + ); + }); }); 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 951adb006f8..653143a6243 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 @@ -1,6 +1,5 @@ import { GlButton } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; -import MockAdapter from 'axios-mock-adapter'; import { nextTick } from 'vue'; import SignInOauthButton from '~/jira_connect/subscriptions/components/sign_in_oauth_button.vue'; @@ -8,11 +7,13 @@ import { I18N_DEFAULT_SIGN_IN_BUTTON_TEXT, OAUTH_WINDOW_OPTIONS, } from '~/jira_connect/subscriptions/constants'; -import axios from '~/lib/utils/axios_utils'; import waitForPromises from 'helpers/wait_for_promises'; -import httpStatus from '~/lib/utils/http_status'; import AccessorUtilities from '~/lib/utils/accessor'; -import { getCurrentUser } from '~/jira_connect/subscriptions/api'; +import { + getCurrentUser, + fetchOAuthApplicationId, + fetchOAuthToken, +} from '~/jira_connect/subscriptions/api'; import createStore from '~/jira_connect/subscriptions/store'; import { SET_ACCESS_TOKEN } from '~/jira_connect/subscriptions/store/mutation_types'; @@ -24,16 +25,17 @@ jest.mock('~/jira_connect/subscriptions/pkce', () => ({ createCodeChallenge: jest.fn().mockResolvedValue('mock-challenge'), })); -const mockOauthMetadata = { - oauth_authorize_url: 'https://gitlab.com/mockOauth', - oauth_token_url: 'https://gitlab.com/mockOauthToken', - state: 'good-state', -}; - describe('SignInOauthButton', () => { let wrapper; - let mockAxios; let store; + const mockOauthMetadata = { + oauth_authorize_url: 'https://gitlab.com/mockOauth', + oauth_token_url: 'https://gitlab.com/mockOauthToken', + oauth_token_payload: { + client_id: '543678901', + }, + state: 'good-state', + }; const createComponent = ({ slots, props } = {}) => { store = createStore(); @@ -50,13 +52,8 @@ describe('SignInOauthButton', () => { }); }; - beforeEach(() => { - mockAxios = new MockAdapter(axios); - }); - afterEach(() => { wrapper.destroy(); - mockAxios.restore(); }); const findButton = () => wrapper.findComponent(GlButton); @@ -70,7 +67,7 @@ describe('SignInOauthButton', () => { }); describe('when `gitlabBasePath` is passed', () => { - const mockBasePath = 'gitlab.mycompany.com'; + const mockBasePath = 'https://gitlab.mycompany.com'; it('uses custom text for button', () => { createComponent({ @@ -81,6 +78,32 @@ describe('SignInOauthButton', () => { expect(findButton().text()).toBe(`Sign in to ${mockBasePath}`); }); + + describe('on click', () => { + const mockClientId = '798412381'; + + beforeEach(async () => { + fetchOAuthApplicationId.mockReturnValue({ data: { application_id: mockClientId } }); + jest.spyOn(window, 'open').mockReturnValue(); + createComponent({ + props: { + gitlabBasePath: mockBasePath, + }, + }); + + findButton().vm.$emit('click'); + + await nextTick(); + }); + + it('calls `window.open` with correct arguments', () => { + expect(window.open).toHaveBeenCalledWith( + `${mockBasePath}/mockOauth?code_challenge=mock-challenge&code_challenge_method=S256&client_id=${mockClientId}`, + I18N_DEFAULT_SIGN_IN_BUTTON_TEXT, + OAUTH_WINDOW_OPTIONS, + ); + }); + }); }); it.each` @@ -110,7 +133,7 @@ describe('SignInOauthButton', () => { it('calls `window.open` with correct arguments', () => { expect(window.open).toHaveBeenCalledWith( - `${mockOauthMetadata.oauth_authorize_url}?code_challenge=mock-challenge&code_challenge_method=S256`, + `${mockOauthMetadata.oauth_authorize_url}?code_challenge=mock-challenge&code_challenge_method=S256&client_id=${mockOauthMetadata.oauth_token_payload.client_id}`, I18N_DEFAULT_SIGN_IN_BUTTON_TEXT, OAUTH_WINDOW_OPTIONS, ); @@ -165,11 +188,7 @@ describe('SignInOauthButton', () => { describe('when API requests succeed', () => { beforeEach(async () => { - jest.spyOn(axios, 'post'); - jest.spyOn(axios, 'get'); - mockAxios - .onPost(mockOauthMetadata.oauth_token_url) - .replyOnce(httpStatus.OK, { access_token: mockAccessToken }); + fetchOAuthToken.mockResolvedValue({ data: { access_token: mockAccessToken } }); getCurrentUser.mockResolvedValue({ data: mockUser }); window.dispatchEvent(new MessageEvent('message', mockEvent)); @@ -178,9 +197,10 @@ describe('SignInOauthButton', () => { }); it('executes POST request to Oauth token endpoint', () => { - expect(axios.post).toHaveBeenCalledWith(mockOauthMetadata.oauth_token_url, { + expect(fetchOAuthToken).toHaveBeenCalledWith(mockOauthMetadata.oauth_token_url, { code: '1234', code_verifier: 'mock-verifier', + client_id: mockOauthMetadata.oauth_token_payload.client_id, }); }); @@ -199,10 +219,7 @@ describe('SignInOauthButton', () => { describe('when API requests fail', () => { beforeEach(async () => { - jest.spyOn(axios, 'post'); - mockAxios - .onPost(mockOauthMetadata.oauth_token_url) - .replyOnce(httpStatus.INTERNAL_SERVER_ERROR); + fetchOAuthToken.mockRejectedValue(); window.dispatchEvent(new MessageEvent('message', mockEvent)); diff --git a/spec/frontend/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/index_spec.js b/spec/frontend/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/index_spec.js index 48f57194363..6b85ca78914 100644 --- a/spec/frontend/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/index_spec.js +++ b/spec/frontend/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/index_spec.js @@ -5,6 +5,17 @@ import SignInGitlabMultiversion from '~/jira_connect/subscriptions/pages/sign_in import VersionSelectForm from '~/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/version_select_form.vue'; import SignInOauthButton from '~/jira_connect/subscriptions/components/sign_in_oauth_button.vue'; +import { updateInstallation } from '~/jira_connect/subscriptions/api'; +import { reloadPage, persistBaseUrl, retrieveBaseUrl } from '~/jira_connect/subscriptions/utils'; + +jest.mock('~/jira_connect/subscriptions/api', () => { + return { + updateInstallation: jest.fn(), + setApiBaseURL: jest.fn(), + }; +}); +jest.mock('~/jira_connect/subscriptions/utils'); + describe('SignInGitlabMultiversion', () => { let wrapper; @@ -31,25 +42,26 @@ describe('SignInGitlabMultiversion', () => { }); describe('when form emits "submit" event', () => { - it('hides the version select form and shows the sign in button', async () => { + it('updates the backend, then saves the baseUrl and reloads', async () => { + updateInstallation.mockResolvedValue({}); + createComponent(); findVersionSelectForm().vm.$emit('submit', mockBasePath); await nextTick(); - expect(findVersionSelectForm().exists()).toBe(false); - expect(findSignInOauthButton().exists()).toBe(true); + expect(updateInstallation).toHaveBeenCalled(); + expect(persistBaseUrl).toHaveBeenCalledWith(mockBasePath); + expect(reloadPage).toHaveBeenCalled(); }); }); }); }); describe('when version is selected', () => { - beforeEach(async () => { + beforeEach(() => { + retrieveBaseUrl.mockReturnValue(mockBasePath); createComponent(); - - findVersionSelectForm().vm.$emit('submit', mockBasePath); - await nextTick(); }); describe('sign in button', () => { diff --git a/spec/frontend/members/mock_data.js b/spec/frontend/members/mock_data.js index 06ccd107ce3..49c4c46c3ac 100644 --- a/spec/frontend/members/mock_data.js +++ b/spec/frontend/members/mock_data.js @@ -23,6 +23,7 @@ export const member = { webUrl: 'https://gitlab.com/root', avatarUrl: 'https://www.gravatar.com/avatar/4816142ef496f956a277bedf1a40607b?s=80&d=identicon', blocked: false, + isBot: false, twoFactorEnabled: false, oncallSchedules: [{ name: 'schedule 1' }], escalationPolicies: [{ name: 'policy 1' }], diff --git a/spec/frontend/members/utils_spec.js b/spec/frontend/members/utils_spec.js index b0c9459ff4f..0271483801c 100644 --- a/spec/frontend/members/utils_spec.js +++ b/spec/frontend/members/utils_spec.js @@ -1,5 +1,12 @@ import setWindowLocation from 'helpers/set_window_location_helper'; -import { DEFAULT_SORT, MEMBER_TYPES } from '~/members/constants'; +import { + DEFAULT_SORT, + MEMBER_TYPES, + I18N_USER_YOU, + I18N_USER_BLOCKED, + I18N_USER_BOT, + I188N_USER_2FA, +} from '~/members/constants'; import { generateBadges, isGroup, @@ -52,9 +59,10 @@ describe('Members Utils', () => { it.each` member | expected - ${memberMock} | ${{ show: true, text: "It's you", variant: 'success' }} - ${{ ...memberMock, user: { ...memberMock.user, blocked: true } }} | ${{ show: true, text: 'Blocked', variant: 'danger' }} - ${member2faEnabled} | ${{ show: true, text: '2FA', variant: 'info' }} + ${memberMock} | ${{ show: true, text: I18N_USER_YOU, variant: 'success' }} + ${{ ...memberMock, user: { ...memberMock.user, blocked: true } }} | ${{ show: true, text: I18N_USER_BLOCKED, variant: 'danger' }} + ${{ ...memberMock, user: { ...memberMock.user, isBot: true } }} | ${{ show: true, text: I18N_USER_BOT, variant: 'muted' }} + ${member2faEnabled} | ${{ show: true, text: I188N_USER_2FA, variant: 'info' }} `('returns expected output for "$expected.text" badge', ({ member, expected }) => { expect( generateBadges({ member, isCurrentUser: true, canManageMembers: true }), diff --git a/spec/frontend/packages_and_registries/harbor_registry/components/list/harbor_list_header_spec.js b/spec/frontend/packages_and_registries/harbor_registry/components/list/harbor_list_header_spec.js index 6602aed0a0c..7a6169d300c 100644 --- a/spec/frontend/packages_and_registries/harbor_registry/components/list/harbor_list_header_spec.js +++ b/spec/frontend/packages_and_registries/harbor_registry/components/list/harbor_list_header_spec.js @@ -7,6 +7,7 @@ import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue'; import { HARBOR_REGISTRY_TITLE, LIST_INTRO_TEXT, + HARBOR_REGISTRY_HELP_PAGE_PATH, } from '~/packages_and_registries/harbor_registry/constants/index'; describe('harbor_list_header', () => { @@ -77,10 +78,10 @@ describe('harbor_list_header', () => { describe('info messages', () => { describe('default message', () => { it('is correctly bound to title_area props', () => { - mountComponent({ helpPagePath: 'foo' }); + mountComponent(); expect(findTitleArea().props('infoMessages')).toEqual([ - { text: LIST_INTRO_TEXT, link: 'foo' }, + { text: LIST_INTRO_TEXT, link: HARBOR_REGISTRY_HELP_PAGE_PATH }, ]); }); }); diff --git a/spec/frontend/packages_and_registries/harbor_registry/mock_data.js b/spec/frontend/packages_and_registries/harbor_registry/mock_data.js index 1bcfcef9102..0ba274ea176 100644 --- a/spec/frontend/packages_and_registries/harbor_registry/mock_data.js +++ b/spec/frontend/packages_and_registries/harbor_registry/mock_data.js @@ -68,7 +68,6 @@ export const defaultConfig = { connectionError: false, invalidPathError: false, isGroupPage: false, - helpPagePath: '', containersErrorImage: 'containersErrorImage', }; diff --git a/spec/lib/gitlab/jira_import_spec.rb b/spec/lib/gitlab/jira_import_spec.rb index 972b0ab6ed1..c0c1a28b9ff 100644 --- a/spec/lib/gitlab/jira_import_spec.rb +++ b/spec/lib/gitlab/jira_import_spec.rb @@ -106,12 +106,6 @@ RSpec.describe Gitlab::JiraImport do end end - describe '.jira_issue_cache_key' do - it 'returns cache key for Jira issue imported to given project' do - expect(described_class.jira_item_cache_key(project_id, 'DEMO-123', :issues)).to eq("jira-import/items-mapper/#{project_id}/issues/DEMO-123") - end - end - describe '.already_imported_cache_key' do it 'returns cache key for already imported items' do expect(described_class.already_imported_cache_key(:issues, project_id)).to eq("jira-importer/already-imported/#{project_id}/issues") diff --git a/spec/lib/gitlab/subscription_portal_spec.rb b/spec/lib/gitlab/subscription_portal_spec.rb index 098a58bff83..f93eb6f96cc 100644 --- a/spec/lib/gitlab/subscription_portal_spec.rb +++ b/spec/lib/gitlab/subscription_portal_spec.rb @@ -53,12 +53,13 @@ RSpec.describe ::Gitlab::SubscriptionPortal do it { is_expected.to match(link_match) } end - context 'url methods' do + describe 'class methods' do where(:method_name, :result) do :default_subscriptions_url | staging_customers_url :payment_form_url | "#{staging_customers_url}/payment_forms/cc_validation" :payment_validation_form_id | 'payment_method_validation' :registration_validation_form_url | "#{staging_customers_url}/payment_forms/cc_registration_validation" + :registration_validation_form_id | 'cc_registration_validation' :subscriptions_graphql_url | "#{staging_customers_url}/graphql" :subscriptions_more_minutes_url | "#{staging_customers_url}/buy_pipeline_minutes" :subscriptions_more_storage_url | "#{staging_customers_url}/buy_storage" @@ -108,4 +109,16 @@ RSpec.describe ::Gitlab::SubscriptionPortal do is_expected.to eq(url) end end + + describe 'constants' do + where(:constant_name, :result) do + 'REGISTRATION_VALIDATION_FORM_ID' | 'cc_registration_validation' + end + + with_them do + subject { "#{described_class}::#{constant_name}".constantize } + + it { is_expected.to eq(result) } + end + end end diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb index f30cc8b6c45..46ed4b57d3a 100644 --- a/spec/lib/gitlab/usage_data_spec.rb +++ b/spec/lib/gitlab/usage_data_spec.rb @@ -763,9 +763,6 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do it { is_expected.to include(:kubernetes_agent_gitops_sync) } it { is_expected.to include(:kubernetes_agent_k8s_api_proxy_request) } - it { is_expected.to include(:package_events_i_package_pull_package) } - it { is_expected.to include(:package_events_i_package_delete_package_by_user) } - it { is_expected.to include(:package_events_i_package_conan_push_package) } end describe '.usage_data_counters' do diff --git a/spec/models/ci/namespace_mirror_spec.rb b/spec/models/ci/namespace_mirror_spec.rb index 3e77c349ccb..29447cbc89d 100644 --- a/spec/models/ci/namespace_mirror_spec.rb +++ b/spec/models/ci/namespace_mirror_spec.rb @@ -16,7 +16,9 @@ RSpec.describe Ci::NamespaceMirror do expect(group1.reload.ci_namespace_mirror).to have_attributes(traversal_ids: [group1.id]) expect(group2.reload.ci_namespace_mirror).to have_attributes(traversal_ids: [group1.id, group2.id]) expect(group3.reload.ci_namespace_mirror).to have_attributes(traversal_ids: [group1.id, group2.id, group3.id]) - expect(group4.reload.ci_namespace_mirror).to have_attributes(traversal_ids: [group1.id, group2.id, group3.id, group4.id]) + expect(group4.reload.ci_namespace_mirror).to have_attributes( + traversal_ids: [group1.id, group2.id, group3.id, group4.id] + ) end context 'scopes' do @@ -103,6 +105,8 @@ RSpec.describe Ci::NamespaceMirror do describe '.sync!' do subject(:sync) { described_class.sync!(Namespaces::SyncEvent.last) } + let(:expected_traversal_ids) { [group1.id, group2.id, group3.id] } + context 'when namespace mirror does not exist in the first place' do let(:namespace) { group3 } @@ -114,7 +118,7 @@ RSpec.describe Ci::NamespaceMirror do it 'creates the mirror' do expect { sync }.to change { described_class.count }.from(3).to(4) - expect(namespace.reload.ci_namespace_mirror).to have_attributes(traversal_ids: [group1.id, group2.id, group3.id]) + expect(namespace.reload.ci_namespace_mirror).to have_attributes(traversal_ids: expected_traversal_ids) end end @@ -128,36 +132,8 @@ RSpec.describe Ci::NamespaceMirror do it 'updates the mirror' do expect { sync }.not_to change { described_class.count } - expect(namespace.reload.ci_namespace_mirror).to have_attributes(traversal_ids: [group1.id, group2.id, group3.id]) - end - end - - shared_context 'changing the middle namespace' do - let(:namespace) { group2 } - - before do - group2.update!(parent: nil) # creates a sync event - end - - it 'updates traversal_ids for the base and descendants' do - expect { sync }.not_to change { described_class.count } - - expect(group1.reload.ci_namespace_mirror).to have_attributes(traversal_ids: [group1.id]) - expect(group2.reload.ci_namespace_mirror).to have_attributes(traversal_ids: [group2.id]) - expect(group3.reload.ci_namespace_mirror).to have_attributes(traversal_ids: [group2.id, group3.id]) - expect(group4.reload.ci_namespace_mirror).to have_attributes(traversal_ids: [group2.id, group3.id, group4.id]) - end - end - - it_behaves_like 'changing the middle namespace' - - context 'when the FFs use_traversal_ids and use_traversal_ids_for_ancestors are disabled' do - before do - stub_feature_flags(use_traversal_ids: false, - use_traversal_ids_for_ancestors: false) + expect(namespace.reload.ci_namespace_mirror).to have_attributes(traversal_ids: expected_traversal_ids) end - - it_behaves_like 'changing the middle namespace' end end end diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index c475b510e62..29ff0641aa9 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -4211,6 +4211,37 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end end + describe '#has_reports?' do + subject { pipeline.has_reports?(Ci::JobArtifact.of_report_type(:test)) } + + let(:pipeline) { create(:ci_pipeline, :running) } + + context 'when pipeline has builds with test reports' do + before do + create(:ci_build, :test_reports, pipeline: pipeline) + end + + it { is_expected.to be_truthy } + end + + context 'when pipeline does not have builds with test reports' do + before do + create(:ci_build, :artifacts, pipeline: pipeline) + end + + it { is_expected.to be_falsey } + end + + context 'when retried build has test reports but latest one has none' do + before do + create(:ci_build, :retried, :test_reports, pipeline: pipeline) + create(:ci_build, :artifacts, pipeline: pipeline) + end + + it { is_expected.to be_falsey } + end + end + describe '#complete_and_has_reports?' do subject { pipeline.complete_and_has_reports?(Ci::JobArtifact.of_report_type(:test)) } @@ -5284,16 +5315,10 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do it { is_expected.to be_falsey } end - context 'when the pipeline is still running' do - let(:pipeline) { create(:ci_pipeline, :running) } - - it { is_expected.to be_falsey } - end - - context 'when the pipeline is completed without test reports' do - let(:pipeline) { create(:ci_pipeline, :success) } + context 'when the pipeline is still running and with test reports' do + let(:pipeline) { create(:ci_pipeline, :running, :with_test_reports) } - it { is_expected.to be_falsey } + it { is_expected.to be_truthy } end end diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb index ea63e27a5fe..9214618f97b 100644 --- a/spec/models/namespace_spec.rb +++ b/spec/models/namespace_spec.rb @@ -439,19 +439,54 @@ RSpec.describe Namespace do context 'traversal_ids on create' do shared_examples 'default traversal_ids' do - let(:namespace) { build(:namespace) } + let!(:namespace) { create(:group) } + let!(:child_namespace) { create(:group, parent: namespace) } - before do - namespace.save! - namespace.reload - end - - it { expect(namespace.traversal_ids).to eq [namespace.id] } + it { expect(namespace.reload.traversal_ids).to eq [namespace.id] } + it { expect(child_namespace.reload.traversal_ids).to eq [namespace.id, child_namespace.id] } + it { expect(namespace.sync_events.count).to eq 1 } + it { expect(child_namespace.sync_events.count).to eq 1 } end it_behaves_like 'default traversal_ids' end + context 'traversal_ids on update' do + let!(:namespace1) { create(:group) } + let!(:namespace2) { create(:group) } + + it 'updates the traversal_ids when the parent_id is changed' do + expect do + namespace1.update!(parent: namespace2) + end.to change { namespace1.reload.traversal_ids }.from([namespace1.id]).to([namespace2.id, namespace1.id]) + end + + it 'creates a Namespaces::SyncEvent using triggers' do + Namespaces::SyncEvent.delete_all + namespace1.update!(parent: namespace2) + expect(namespace1.reload.sync_events.count).to eq(1) + end + + it 'creates sync_events using database trigger on the table' do + expect { Group.update_all(traversal_ids: [-1]) }.to change(Namespaces::SyncEvent, :count).by(2) + end + + it 'does not create sync_events using database trigger on the table when only the parent_id has changed' do + expect { Group.update_all(parent_id: -1) }.not_to change(Namespaces::SyncEvent, :count) + end + + it 'triggers the callback sync_traversal_ids on the namespace' do + allow(namespace1).to receive(:run_callbacks).and_call_original + expect(namespace1).to receive(:run_callbacks).with(:sync_traversal_ids) + namespace1.update!(parent: namespace2) + end + + it 'calls schedule_sync_event_worker on the updated namespace' do + expect(namespace1).to receive(:schedule_sync_event_worker) + namespace1.update!(parent: namespace2) + end + end + describe "after_commit :expire_child_caches" do let(:namespace) { create(:group) } @@ -2216,6 +2251,20 @@ RSpec.describe Namespace do expect(namespace.sync_events.count).to eq(2) end + it 'creates a namespaces_sync_event for the parent and all the descendent namespaces' do + children_namespaces = create_list(:group, 2, parent_id: namespace.id) + grand_children_namespaces = create_list(:group, 2, parent_id: children_namespaces.first.id) + expect(Namespaces::ProcessSyncEventsWorker).to receive(:perform_async).exactly(:once) + Namespaces::SyncEvent.delete_all + + expect do + namespace.update!(parent_id: new_namespace1.id) + end.to change(Namespaces::SyncEvent, :count).by(5) + + expected_ids = [namespace.id] + children_namespaces.map(&:id) + grand_children_namespaces.map(&:id) + expect(Namespaces::SyncEvent.pluck(:namespace_id)).to match_array(expected_ids) + end + it 'enqueues ProcessSyncEventsWorker' do expect(Namespaces::ProcessSyncEventsWorker).to receive(:perform_async) diff --git a/spec/models/namespaces/sync_event_spec.rb b/spec/models/namespaces/sync_event_spec.rb new file mode 100644 index 00000000000..a3a90ba9aff --- /dev/null +++ b/spec/models/namespaces/sync_event_spec.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Namespaces::SyncEvent, type: :model do + describe '.enqueue_worker' do + it 'schedules Namespaces::ProcessSyncEventsWorker job' do + expect(::Namespaces::ProcessSyncEventsWorker).to receive(:perform_async) + described_class.enqueue_worker + end + end + + describe '.upper_bound_count' do + it 'returns 0 when there are no records in the table' do + expect(described_class.upper_bound_count).to eq(0) + end + + it 'returns an estimated number of the records in the database' do + create_list(:namespace, 3) + expect(described_class.upper_bound_count).to eq(3) + end + end +end diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb index ca558848cb0..1fce1f97dcb 100644 --- a/spec/models/note_spec.rb +++ b/spec/models/note_spec.rb @@ -280,6 +280,32 @@ RSpec.describe Note do expect { note.destroy! }.not_to raise_error end end + + describe 'sets internal flag' do + subject(:internal) { note.reload.internal } + + let(:note) { create(:note, confidential: confidential, project: issue.project, noteable: issue) } + + let_it_be(:issue) { create(:issue) } + + context 'when confidential is `true`' do + let(:confidential) { true } + + it { is_expected.to be true } + end + + context 'when confidential is `false`' do + let(:confidential) { false } + + it { is_expected.to be false } + end + + context 'when confidential is `nil`' do + let(:confidential) { nil } + + it { is_expected.to be false } + end + end end describe "Commit notes" do diff --git a/spec/requests/api/usage_data_spec.rb b/spec/requests/api/usage_data_spec.rb index ea50c404d92..d532fb6c168 100644 --- a/spec/requests/api/usage_data_spec.rb +++ b/spec/requests/api/usage_data_spec.rb @@ -138,7 +138,9 @@ RSpec.describe API::UsageData do context 'with correct params' do it 'returns status ok' do - expect(Gitlab::Redis::HLL).to receive(:add) + expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track).with(anything, known_event, anything) + # allow other events to also get triggered + allow(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track) post api(endpoint, user), params: { event: known_event } diff --git a/spec/serializers/member_user_entity_spec.rb b/spec/serializers/member_user_entity_spec.rb index 4dd6848c47b..638347738f2 100644 --- a/spec/serializers/member_user_entity_spec.rb +++ b/spec/serializers/member_user_entity_spec.rb @@ -27,6 +27,12 @@ RSpec.describe MemberUserEntity do expect(entity_hash[:blocked]).to be(true) end + it 'correctly exposes `is_bot`' do + allow(user).to receive(:bot?).and_return(true) + + expect(entity_hash[:is_bot]).to be(true) + end + it 'does not expose `two_factor_enabled` by default' do expect(entity_hash[:two_factor_enabled]).to be(nil) end diff --git a/spec/services/ci/process_sync_events_service_spec.rb b/spec/services/ci/process_sync_events_service_spec.rb index 241ac4995ff..7ab7911e578 100644 --- a/spec/services/ci/process_sync_events_service_spec.rb +++ b/spec/services/ci/process_sync_events_service_spec.rb @@ -120,13 +120,15 @@ RSpec.describe Ci::ProcessSyncEventsService do before do Namespaces::SyncEvent.delete_all + # Creates a sync event for group, and the ProjectNamespace of project1 & project2: 3 in total group.update!(parent: parent_group_2) + # Creates a sync event for parent_group2 and all the children: 4 in total parent_group_2.update!(parent: parent_group_1) end shared_examples 'event consuming' do it 'consumes events' do - expect { execute }.to change(Namespaces::SyncEvent, :count).from(2).to(0) + expect { execute }.to change(Namespaces::SyncEvent, :count).from(7).to(0) expect(group.reload.ci_namespace_mirror).to have_attributes( traversal_ids: [parent_group_1.id, parent_group_2.id, group.id] @@ -134,6 +136,12 @@ RSpec.describe Ci::ProcessSyncEventsService do expect(parent_group_2.reload.ci_namespace_mirror).to have_attributes( traversal_ids: [parent_group_1.id, parent_group_2.id] ) + expect(project1.reload.project_namespace).to have_attributes( + traversal_ids: [parent_group_1.id, parent_group_2.id, group.id, project1.project_namespace.id] + ) + expect(project2.reload.project_namespace).to have_attributes( + traversal_ids: [parent_group_1.id, parent_group_2.id, group.id, project2.project_namespace.id] + ) end end @@ -157,7 +165,7 @@ RSpec.describe Ci::ProcessSyncEventsService do end it 'does not enqueue Namespaces::ProcessSyncEventsWorker if no left' do - stub_const("#{described_class}::BATCH_SIZE", 2) + stub_const("#{described_class}::BATCH_SIZE", 7) expect(Namespaces::ProcessSyncEventsWorker).not_to receive(:perform_async) |