diff --git a/app/assets/javascripts/members/placeholders/components/placeholder_actions.vue b/app/assets/javascripts/members/placeholders/components/placeholder_actions.vue
index 739a5a4701f..84f69773267 100644
--- a/app/assets/javascripts/members/placeholders/components/placeholder_actions.vue
+++ b/app/assets/javascripts/members/placeholders/components/placeholder_actions.vue
@@ -281,13 +281,13 @@ export default {
-
+
{{ __('This field is required.') }}
+
+ {{ sourceUser.reassignmentError }}
+
diff --git a/app/assets/javascripts/members/placeholders/graphql/fragments/import_source_user.fragment.graphql b/app/assets/javascripts/members/placeholders/graphql/fragments/import_source_user.fragment.graphql
index 0eb19fe181e..23ea403d854 100644
--- a/app/assets/javascripts/members/placeholders/graphql/fragments/import_source_user.fragment.graphql
+++ b/app/assets/javascripts/members/placeholders/graphql/fragments/import_source_user.fragment.graphql
@@ -6,6 +6,7 @@ fragment ImportSourceUser on ImportSourceUser {
sourceName
sourceHostname
status
+ reassignmentError
placeholderUser {
...User
}
diff --git a/app/assets/javascripts/pages/profiles/two_factor_auths/index.js b/app/assets/javascripts/pages/profiles/two_factor_auths/index.js
index 41952a33c05..cebb24e133c 100644
--- a/app/assets/javascripts/pages/profiles/two_factor_auths/index.js
+++ b/app/assets/javascripts/pages/profiles/two_factor_auths/index.js
@@ -1,6 +1,10 @@
import { mount2faRegistration } from '~/authentication/mount_2fa';
import { initWebAuthnRegistration } from '~/authentication/webauthn/registration';
-import { initRecoveryCodes, initManageTwoFactorForm } from '~/authentication/two_factor_auth';
+import {
+ initRecoveryCodes,
+ initManageTwoFactorForm,
+ initTwoFactorConfirm,
+} from '~/authentication/two_factor_auth';
import { parseBoolean } from '~/lib/utils/common_utils';
const twoFactorNode = document.querySelector('.js-two-factor-auth');
@@ -21,3 +25,4 @@ mount2faRegistration();
initWebAuthnRegistration();
initRecoveryCodes();
initManageTwoFactorForm();
+initTwoFactorConfirm();
diff --git a/app/assets/javascripts/pages/users/index.js b/app/assets/javascripts/pages/users/index.js
index 134962721d2..872c71fa8b3 100644
--- a/app/assets/javascripts/pages/users/index.js
+++ b/app/assets/javascripts/pages/users/index.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
import { setCookie } from '~/lib/utils/common_utils';
import UserCallout from '~/user_callout';
-import { initProfileTabs, initUserAchievements } from '~/profile';
+import { initUserAchievements, initUserProfileApp } from '~/profile';
import { initUserActionsApp } from '~/users/profile/actions';
import UserTabs from './user_tabs';
@@ -11,7 +11,7 @@ function initUserProfile(action) {
// See https://gitlab.com/gitlab-org/gitlab/-/issues/435899.
if (gon.features?.profileTabsVue) {
- initProfileTabs();
+ initUserProfileApp();
} else {
// eslint-disable-next-line no-new
new UserTabs({ parentEl: '.user-profile', action });
diff --git a/app/assets/javascripts/profile/components/app.vue b/app/assets/javascripts/profile/components/app.vue
new file mode 100644
index 00000000000..14313c92ab4
--- /dev/null
+++ b/app/assets/javascripts/profile/components/app.vue
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/app/assets/javascripts/profile/components/profile_tabs.vue b/app/assets/javascripts/profile/components/profile_tabs.vue
index a15794ac07d..c566dc6d939 100644
--- a/app/assets/javascripts/profile/components/profile_tabs.vue
+++ b/app/assets/javascripts/profile/components/profile_tabs.vue
@@ -17,6 +17,7 @@ import FollowersTab from './followers_tab.vue';
import FollowingTab from './following_tab.vue';
export default {
+ name: 'ProfileTabs',
i18n: {
personalProjectsErrorMessage: s__(
'UserProfile|An error occurred loading the personal projects. Please refresh the page to try again.',
diff --git a/app/assets/javascripts/profile/constants.js b/app/assets/javascripts/profile/constants.js
index 9d3dcd648a8..771169e1e7d 100644
--- a/app/assets/javascripts/profile/constants.js
+++ b/app/assets/javascripts/profile/constants.js
@@ -7,3 +7,5 @@ export const CALENDAR_PERIOD_12_MONTHS = 12;
export const OVERVIEW_CALENDAR_BREAKPOINT = 918;
export const SNIPPET_MAX_LIST_COUNT = 20;
+
+export const USER_PROFILE_ROUTE_NAME_DEFAULT = 'default';
diff --git a/app/assets/javascripts/profile/index.js b/app/assets/javascripts/profile/index.js
index 76430d7b34d..31faa327fa7 100644
--- a/app/assets/javascripts/profile/index.js
+++ b/app/assets/javascripts/profile/index.js
@@ -1,15 +1,37 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
+import VueRouter from 'vue-router';
import createDefaultClient from '~/lib/graphql';
-
-import ProfileTabs from './components/profile_tabs.vue';
+import { USER_PROFILE_ROUTE_NAME_DEFAULT } from '~/profile/constants';
+import UserProfileApp from './components/app.vue';
import UserAchievements from './components/user_achievements.vue';
+import ProfileTabs from './components/profile_tabs.vue';
Vue.use(VueApollo);
+Vue.use(VueRouter);
-export const initProfileTabs = () => {
- const el = document.getElementById('js-profile-tabs');
+export const createRouter = () => {
+ const routes = [
+ {
+ name: USER_PROFILE_ROUTE_NAME_DEFAULT,
+ path: '/:user*',
+ component: ProfileTabs,
+ },
+ ];
+
+ return new VueRouter({
+ routes,
+ mode: 'history',
+ base: '/',
+ scrollBehavior(to, from, savedPosition) {
+ return savedPosition || { x: 0, y: 0 };
+ },
+ });
+};
+
+export const initUserProfileApp = () => {
+ const el = document.getElementById('js-user-profile-app');
if (!el) return false;
@@ -33,6 +55,7 @@ export const initProfileTabs = () => {
el,
apolloProvider,
name: 'ProfileRoot',
+ router: createRouter(),
provide: {
followeesCount: parseInt(followeesCount, 10),
followersCount: parseInt(followersCount, 10),
@@ -45,7 +68,7 @@ export const initProfileTabs = () => {
followEmptyState,
},
render(createElement) {
- return createElement(ProfileTabs);
+ return createElement(UserProfileApp);
},
});
};
diff --git a/app/assets/javascripts/projects/your_work/components/tab_view.vue b/app/assets/javascripts/projects/your_work/components/tab_view.vue
index 18bbfeda653..44fe7bcf7fd 100644
--- a/app/assets/javascripts/projects/your_work/components/tab_view.vue
+++ b/app/assets/javascripts/projects/your_work/components/tab_view.vue
@@ -47,7 +47,7 @@ export default {
return {
query: this.tab.query,
variables() {
- return this.pagination;
+ return { ...this.pagination, ...this.tab.variables };
},
update(response) {
const { nodes, pageInfo } = get(response, this.tab.queryPath);
diff --git a/app/assets/javascripts/projects/your_work/constants.js b/app/assets/javascripts/projects/your_work/constants.js
index 7039164ec39..27426f611a8 100644
--- a/app/assets/javascripts/projects/your_work/constants.js
+++ b/app/assets/javascripts/projects/your_work/constants.js
@@ -1,42 +1,44 @@
import { __ } from '~/locale';
-import contributedProjectsQuery from './graphql/queries/contributed_projects.query.graphql';
-import personalProjectsQuery from './graphql/queries/personal_projects.query.graphql';
-import membershipProjectsQuery from './graphql/queries/membership_projects.query.graphql';
-import starredProjectsQuery from './graphql/queries/starred_projects.query.graphql';
-import inactiveProjectsQuery from './graphql/queries/inactive_projects.query.graphql';
+import projectsQuery from './graphql/queries/projects.query.graphql';
+import userProjectsQuery from './graphql/queries/user_projects.query.graphql';
export const CONTRIBUTED_TAB = {
text: __('Contributed'),
value: 'contributed',
- query: contributedProjectsQuery,
+ query: userProjectsQuery,
+ variables: { contributed: true },
queryPath: 'currentUser.contributedProjects',
};
export const STARRED_TAB = {
text: __('Starred'),
value: 'starred',
- query: starredProjectsQuery,
+ query: userProjectsQuery,
+ variables: { starred: true },
queryPath: 'currentUser.starredProjects',
};
export const PERSONAL_TAB = {
text: __('Personal'),
value: 'personal',
- query: personalProjectsQuery,
+ query: projectsQuery,
+ variables: { personal: true },
queryPath: 'projects',
};
export const MEMBER_TAB = {
text: __('Member'),
value: 'member',
- query: membershipProjectsQuery,
+ query: projectsQuery,
+ variables: { membership: true },
queryPath: 'projects',
};
export const INACTIVE_TAB = {
text: __('Inactive'),
value: 'inactive',
- query: inactiveProjectsQuery,
+ query: projectsQuery,
+ variables: { archived: 'ONLY', membership: true },
queryPath: 'projects',
};
diff --git a/app/assets/javascripts/projects/your_work/graphql/queries/contributed_projects.query.graphql b/app/assets/javascripts/projects/your_work/graphql/queries/contributed_projects.query.graphql
deleted file mode 100644
index 161c6da3457..00000000000
--- a/app/assets/javascripts/projects/your_work/graphql/queries/contributed_projects.query.graphql
+++ /dev/null
@@ -1,16 +0,0 @@
-#import "~/graphql_shared/fragments/page_info.fragment.graphql"
-#import "ee_else_ce/graphql_shared/fragments/project.fragment.graphql"
-
-query getContributedProjects($first: Int, $last: Int, $before: String, $after: String) {
- currentUser {
- id
- contributedProjects(first: $first, last: $last, before: $before, after: $after) {
- nodes {
- ...Project
- }
- pageInfo {
- ...PageInfo
- }
- }
- }
-}
diff --git a/app/assets/javascripts/projects/your_work/graphql/queries/membership_projects.query.graphql b/app/assets/javascripts/projects/your_work/graphql/queries/membership_projects.query.graphql
deleted file mode 100644
index f18ab0212b6..00000000000
--- a/app/assets/javascripts/projects/your_work/graphql/queries/membership_projects.query.graphql
+++ /dev/null
@@ -1,13 +0,0 @@
-#import "~/graphql_shared/fragments/page_info.fragment.graphql"
-#import "ee_else_ce/graphql_shared/fragments/project.fragment.graphql"
-
-query getMembershipProjects($first: Int, $last: Int, $before: String, $after: String) {
- projects(membership: true, first: $first, last: $last, before: $before, after: $after) {
- nodes {
- ...Project
- }
- pageInfo {
- ...PageInfo
- }
- }
-}
diff --git a/app/assets/javascripts/projects/your_work/graphql/queries/personal_projects.query.graphql b/app/assets/javascripts/projects/your_work/graphql/queries/personal_projects.query.graphql
deleted file mode 100644
index f4cc871f1f4..00000000000
--- a/app/assets/javascripts/projects/your_work/graphql/queries/personal_projects.query.graphql
+++ /dev/null
@@ -1,13 +0,0 @@
-#import "~/graphql_shared/fragments/page_info.fragment.graphql"
-#import "ee_else_ce/graphql_shared/fragments/project.fragment.graphql"
-
-query getPersonalProjects($first: Int, $last: Int, $before: String, $after: String) {
- projects(personal: true, first: $first, last: $last, before: $before, after: $after) {
- nodes {
- ...Project
- }
- pageInfo {
- ...PageInfo
- }
- }
-}
diff --git a/app/assets/javascripts/projects/your_work/graphql/queries/inactive_projects.query.graphql b/app/assets/javascripts/projects/your_work/graphql/queries/projects.query.graphql
similarity index 53%
rename from app/assets/javascripts/projects/your_work/graphql/queries/inactive_projects.query.graphql
rename to app/assets/javascripts/projects/your_work/graphql/queries/projects.query.graphql
index 99d4cb30186..1658e4d3fb7 100644
--- a/app/assets/javascripts/projects/your_work/graphql/queries/inactive_projects.query.graphql
+++ b/app/assets/javascripts/projects/your_work/graphql/queries/projects.query.graphql
@@ -1,10 +1,19 @@
#import "~/graphql_shared/fragments/page_info.fragment.graphql"
#import "ee_else_ce/graphql_shared/fragments/project.fragment.graphql"
-query getInactiveProjects($first: Int, $last: Int, $before: String, $after: String) {
+query getYourWorkProjects(
+ $archived: ProjectArchived = EXCLUDE
+ $membership: Boolean = false
+ $personal: Boolean = false
+ $first: Int
+ $last: Int
+ $before: String
+ $after: String
+) {
projects(
- archived: ONLY
- membership: true
+ archived: $archived
+ membership: $membership
+ personal: $personal
first: $first
last: $last
before: $before
diff --git a/app/assets/javascripts/projects/your_work/graphql/queries/starred_projects.query.graphql b/app/assets/javascripts/projects/your_work/graphql/queries/starred_projects.query.graphql
deleted file mode 100644
index d2df5f2804a..00000000000
--- a/app/assets/javascripts/projects/your_work/graphql/queries/starred_projects.query.graphql
+++ /dev/null
@@ -1,16 +0,0 @@
-#import "~/graphql_shared/fragments/page_info.fragment.graphql"
-#import "ee_else_ce/graphql_shared/fragments/project.fragment.graphql"
-
-query getStarredProjects($first: Int, $last: Int, $before: String, $after: String) {
- currentUser {
- id
- starredProjects(first: $first, last: $last, before: $before, after: $after) {
- nodes {
- ...Project
- }
- pageInfo {
- ...PageInfo
- }
- }
- }
-}
diff --git a/app/assets/javascripts/projects/your_work/graphql/queries/user_projects.query.graphql b/app/assets/javascripts/projects/your_work/graphql/queries/user_projects.query.graphql
new file mode 100644
index 00000000000..07bdfd921af
--- /dev/null
+++ b/app/assets/javascripts/projects/your_work/graphql/queries/user_projects.query.graphql
@@ -0,0 +1,33 @@
+#import "~/graphql_shared/fragments/page_info.fragment.graphql"
+#import "ee_else_ce/graphql_shared/fragments/project.fragment.graphql"
+
+query getYourWorkUserProjects(
+ $contributed: Boolean = false
+ $starred: Boolean = false
+ $first: Int
+ $last: Int
+ $before: String
+ $after: String
+) {
+ currentUser {
+ id
+ contributedProjects(first: $first, last: $last, before: $before, after: $after)
+ @include(if: $contributed) {
+ nodes {
+ ...Project
+ }
+ pageInfo {
+ ...PageInfo
+ }
+ }
+ starredProjects(first: $first, last: $last, before: $before, after: $after)
+ @include(if: $starred) {
+ nodes {
+ ...Project
+ }
+ pageInfo {
+ ...PageInfo
+ }
+ }
+ }
+}
diff --git a/app/assets/stylesheets/components/avatar.scss b/app/assets/stylesheets/components/avatar.scss
index 8047de768a0..6d984a0922f 100644
--- a/app/assets/stylesheets/components/avatar.scss
+++ b/app/assets/stylesheets/components/avatar.scss
@@ -67,7 +67,7 @@ $avatar-sizes: (
.avatar,
.avatar-container {
float: left;
- margin-right: $gl-padding;
+ margin-right: $gl-padding-8;
border-radius: 50%;
@each $size, $size-config in $avatar-sizes {
@@ -79,8 +79,8 @@ $avatar-sizes: (
.avatar {
transition-property: none;
- width: 40px;
- height: 40px;
+ width: 32px;
+ height: 32px;
padding: 0;
background: var(--gl-background-color-subtle);
overflow: hidden;
diff --git a/app/assets/stylesheets/framework/page_header.scss b/app/assets/stylesheets/framework/page_header.scss
index ad183a64cc5..8888b7cde0b 100644
--- a/app/assets/stylesheets/framework/page_header.scss
+++ b/app/assets/stylesheets/framework/page_header.scss
@@ -21,6 +21,11 @@
@include media-breakpoint-up(sm) {
margin-left: 4px;
}
+
+ &.s24 {
+ margin-top: -2px;
+ margin-right: 4px;
+ }
}
.commit-committer-link,
diff --git a/app/controllers/profiles/two_factor_auths_controller.rb b/app/controllers/profiles/two_factor_auths_controller.rb
index d8052809572..c2dfa3dabec 100644
--- a/app/controllers/profiles/two_factor_auths_controller.rb
+++ b/app/controllers/profiles/two_factor_auths_controller.rb
@@ -135,7 +135,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
error_message = { message: _('You must provide a valid current password.') }
if params[:action] == 'create_webauthn'
@webauthn_error = error_message
- elsif params[:action] == 'destroy_otp'
+ elsif params[:action] == 'destroy_otp' || Feature.enabled?(:two_factor_actions)
@destroy_error = error_message
else
@error = error_message
diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb
index 82c7023537f..05963d026fe 100644
--- a/app/helpers/auth_helper.rb
+++ b/app/helpers/auth_helper.rb
@@ -200,6 +200,50 @@ module AuthHelper
end
end
+ def delete_otp_authenticator_data(password_required)
+ message = if password_required
+ _('Are you sure you want to delete this one-time password authenticator? ' \
+ 'Enter your password to continue.')
+ else
+ _('Are you sure you want to delete this one-time password authenticator?')
+ end
+
+ { button_text: _('Delete one-time password authenticator'),
+ message: message,
+ path: destroy_otp_profile_two_factor_auth_path,
+ password_required: password_required.to_s }
+ end
+
+ def disable_two_factor_authentication_data(password_required)
+ message = if password_required
+ _('Are you sure you want to invalidate your one-time password authenticator and WebAuthn devices? ' \
+ 'Enter your password to continue. This action cannot be undone.')
+ else
+ _('Are you sure you want to invalidate your one-time password authenticator and WebAuthn devices?')
+ end
+
+ { button_text: _('Disable two-factor authentication'),
+ message: message,
+ path: profile_two_factor_auth_path,
+ password_required: password_required.to_s }
+ end
+
+ def codes_two_factor_authentication_data(password_required)
+ message = if password_required
+ _('Are you sure you want to regenerate recovery codes? ' \
+ 'Enter your password to continue.')
+ else
+ _('Are you sure you want to regenerate recovery codes?')
+ end
+
+ { button_text: _('Regenerate recovery codes'),
+ message: message,
+ method: 'post',
+ path: codes_profile_two_factor_auth_path,
+ password_required: password_required.to_s,
+ variant: 'default' }
+ end
+
extend self
end
diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb
index 44028bb876d..0038a288403 100644
--- a/app/helpers/users_helper.rb
+++ b/app/helpers/users_helper.rb
@@ -209,7 +209,7 @@ module UsersHelper
user.public_email.present?
end
- def user_profile_tabs_app_data(user)
+ def user_profile_app_data(user)
{
followees_count: user.followees.count,
followers_count: user.followers.count,
diff --git a/app/views/profiles/two_factor_auths/show.html.haml b/app/views/profiles/two_factor_auths/show.html.haml
index 07be8c7f647..d2c392f9bc2 100644
--- a/app/views/profiles/two_factor_auths/show.html.haml
+++ b/app/views/profiles/two_factor_auths/show.html.haml
@@ -19,14 +19,17 @@
= _('Register a one-time password authenticator')
%p
= _('Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA).')
- .col-lg-8{ data: { testid: 'otp' } }
+ .col-lg-8
- if current_user.two_factor_otp_enabled?
%p
- if Feature.enabled?(:delete_otp_no_webauthn)
= _("You've already enabled two-factor authentication using a one-time password authenticator. In order to register a different device, you must first delete this authenticator.")
- else
= _("You've already enabled two-factor authentication using a one-time password authenticator. In order to register a different device, you must first disable two-factor authentication.")
- - if Feature.enabled?(:delete_otp_no_webauthn)
+ - if Feature.enabled?(:delete_otp_no_webauthn) && Feature.enabled?(:two_factor_actions)
+ .gl-inline-block.gl-w-full.sm:gl-w-auto
+ .js-two-factor-action-confirm{ data: delete_otp_authenticator_data(current_password_required?) }
+ - elsif Feature.enabled?(:delete_otp_no_webauthn)
= gitlab_ui_form_for(:user, url: destroy_otp_profile_two_factor_auth_path, method: :delete, html: { class: 'sm:gl-inline-block' }) do |f|
- if current_password_required?
.form-group
@@ -144,7 +147,7 @@
= _('Disable two-factor authentication')
%p
= _('Use this section to disable your one-time password authenticator and WebAuthn devices. You can also generate new recovery codes.')
- .col-lg-8{ data: { testid: 'disable_two_factor' } }
+ .col-lg-8
- if current_user.two_factor_enabled?
%p
= _('If you lose your recovery codes you can generate new ones, invalidating all previous codes.')
@@ -155,7 +158,14 @@
dismissible: false) do |c|
- c.with_body do
= troubleshooting_link
- .js-manage-two-factor-form{ data: { current_password_required: current_password_required?.to_s, profile_two_factor_auth_path: profile_two_factor_auth_path, profile_two_factor_auth_method: 'delete', codes_profile_two_factor_auth_path: codes_profile_two_factor_auth_path, codes_profile_two_factor_auth_method: 'post' } }
+ - if Feature.enabled?(:two_factor_actions)
+ .gl-flex.gl-flex-wrap.gl-gap-3
+ .gl-w-full.sm:gl-w-auto
+ .js-two-factor-action-confirm{ data: disable_two_factor_authentication_data(current_password_required?) }
+ .gl-w-full.sm:gl-w-auto
+ .js-two-factor-action-confirm{ data: codes_two_factor_authentication_data(current_password_required?) }
+ - else
+ .js-manage-two-factor-form{ data: { current_password_required: current_password_required?.to_s, profile_two_factor_auth_path: profile_two_factor_auth_path, profile_two_factor_auth_method: 'delete', codes_profile_two_factor_auth_path: codes_profile_two_factor_auth_path, codes_profile_two_factor_auth_method: 'post' } }
- else
%p
= _("Register a one-time password authenticator or a WebAuthn device first.")
diff --git a/app/views/projects/commit/_commit_box.html.haml b/app/views/projects/commit/_commit_box.html.haml
index 0fe2005fb98..8dc6f032a5b 100644
--- a/app/views/projects/commit/_commit_box.html.haml
+++ b/app/views/projects/commit/_commit_box.html.haml
@@ -11,14 +11,13 @@
%span.gl-hidden.sm:gl-inline= _('authored')
#{time_ago_with_tooltip(@commit.authored_date)}
%span= s_('ByAuthor|by')
- = author_avatar(@commit, size: 24, has_tooltip: false)
%strong
+ = author_avatar(@commit, size: 24, has_tooltip: false)
= commit_author_link(@commit, avatar: true, size: 24)
= user_status(@commit.author)
- if @commit.different_committer?
- %span.light= _('Committed by')
- %strong
- = commit_committer_link(@commit, avatar: true, size: 24)
+ %span.gl-text-subtle= _('Committed by')
+ = commit_committer_link(@commit, avatar: true, size: 24)
#{time_ago_with_tooltip(@commit.committed_date)}
= link_button_to _('Browse files'), project_tree_path(@project, @commit), class: 'gl-mr-3 gl-w-full sm:gl-w-auto gl-mb-3 sm:gl-mb-0'
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index 7a0abad7068..d5a2fc82f8d 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -26,7 +26,7 @@
%li{ class: ["commit flex-row", ("js-toggle-container" if collapsible)], id: "commit-#{commit.short_id}" }
.gl-self-start.gl-hidden.sm:gl-block
- = author_avatar(commit, size: 40, has_tooltip: false)
+ = author_avatar(commit, size: 32, has_tooltip: false)
.commit-detail.flex-list.gl-flex.gl-justify-between.gl-items-center.gl-grow.gl-min-w-0
.commit-content{ data: { testid: 'commit-content' } }
diff --git a/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml b/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml
index 134d3b91df1..7e8c2c4275e 100644
--- a/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml
+++ b/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml
@@ -49,7 +49,7 @@
%span.pipeline-id ##{generic_commit_status.pipeline.id}
%span by
- if generic_commit_status.pipeline.user
- = user_avatar(user: generic_commit_status.pipeline.user, size: 20)
+ = user_avatar(user: generic_commit_status.pipeline.user, size: 24)
- else
%span.monospace API
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index dcc0ca6ec68..bde6d79c051 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -46,7 +46,7 @@
.user-profile-content
- if allowable_actions.any?
- if Feature.enabled?(:profile_tabs_vue, current_user)
- #js-profile-tabs{ data: user_profile_tabs_app_data(@user) }
+ #js-user-profile-app{ data: user_profile_app_data(@user) }
- else
= render 'users/legacy_tabs', action: @action, endpoint: @endpoint, allowable_actions: allowable_actions
.loading.hide
diff --git a/config/feature_flags/gitlab_com_derisk/two_factor_actions.yml b/config/feature_flags/gitlab_com_derisk/two_factor_actions.yml
new file mode 100644
index 00000000000..a2a2e957adb
--- /dev/null
+++ b/config/feature_flags/gitlab_com_derisk/two_factor_actions.yml
@@ -0,0 +1,9 @@
+---
+name: two_factor_actions
+feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/393419
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/167338
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/491760
+milestone: '17.5'
+group: group::authentication
+type: gitlab_com_derisk
+default_enabled: false
diff --git a/db/docs/zoekt_shards.yml b/db/docs/deleted_tables/zoekt_shards.yml
similarity index 80%
rename from db/docs/zoekt_shards.yml
rename to db/docs/deleted_tables/zoekt_shards.yml
index 93b99993903..7f39ddb0089 100644
--- a/db/docs/zoekt_shards.yml
+++ b/db/docs/deleted_tables/zoekt_shards.yml
@@ -9,3 +9,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/105049
milestone: '15.9'
gitlab_schema: gitlab_main_cell
exempt_from_sharding: true # table scheduled for deletion https://gitlab.com/gitlab-org/gitlab/-/issues/473263
+removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/167720
+removed_in_milestone: '17.5'
diff --git a/db/post_migrate/20240930120430_drop_zoekt_shards.rb b/db/post_migrate/20240930120430_drop_zoekt_shards.rb
new file mode 100644
index 00000000000..88a0355f8f9
--- /dev/null
+++ b/db/post_migrate/20240930120430_drop_zoekt_shards.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+class DropZoektShards < Gitlab::Database::Migration[2.2]
+ disable_ddl_transaction!
+ milestone '17.5'
+
+ def up
+ drop_table :zoekt_shards
+ end
+
+ def down
+ create_table :zoekt_shards do |t|
+ t.text :index_base_url, null: false, limit: 1024
+ t.text :search_base_url, null: false, limit: 1024
+ t.timestamps_with_timezone
+ t.uuid :uuid, null: false, default: '00000000-00000000-00000000-00000000'
+ t.datetime_with_timezone :last_seen_at, null: false, default: '1970-01-01'
+ t.bigint :used_bytes, null: false, default: 0
+ t.bigint :total_bytes, null: false, default: 0
+ t.jsonb :metadata, null: false, default: {}
+ end
+
+ add_concurrent_index :zoekt_shards, :index_base_url, unique: true, name: 'index_zoekt_shards_on_index_base_url'
+ add_concurrent_index :zoekt_shards, :last_seen_at, name: 'index_zoekt_shards_on_last_seen_at'
+ add_concurrent_index :zoekt_shards, :search_base_url, unique: true, name: 'index_zoekt_shards_on_search_base_url'
+ add_concurrent_index :zoekt_shards, :uuid, unique: true, name: 'unique_zoekt_shards_uuid'
+ end
+end
diff --git a/db/post_migrate/20241001153138_remove_gin_index_from_sbom_components.rb b/db/post_migrate/20241001153138_remove_gin_index_from_sbom_components.rb
new file mode 100644
index 00000000000..03f24906cfa
--- /dev/null
+++ b/db/post_migrate/20241001153138_remove_gin_index_from_sbom_components.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+class RemoveGinIndexFromSbomComponents < Gitlab::Database::Migration[2.2]
+ disable_ddl_transaction!
+ milestone '17.5'
+ INDEX_NAME = "idx_sbom_components_on_name_gin"
+ def up
+ prepare_async_index_removal :sbom_components, :name, name: INDEX_NAME
+ end
+
+ def down
+ unprepare_async_index :sbom_components, :name, name: INDEX_NAME
+ end
+end
diff --git a/db/schema_migrations/20240930120430 b/db/schema_migrations/20240930120430
new file mode 100644
index 00000000000..a54e8a69eb0
--- /dev/null
+++ b/db/schema_migrations/20240930120430
@@ -0,0 +1 @@
+f3544687ee89d60918a396a7c22bd927eb4ce3045eb96191e61b4fc4fb562528
\ No newline at end of file
diff --git a/db/schema_migrations/20241001153138 b/db/schema_migrations/20241001153138
new file mode 100644
index 00000000000..3ed58d2b37a
--- /dev/null
+++ b/db/schema_migrations/20241001153138
@@ -0,0 +1 @@
+a29ddb764366e4166c284e964afeddb7ecc99c7c76a7e1ab1f471846d633be86
\ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 04609bedd92..ffda14de1a3 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -21461,30 +21461,6 @@ CREATE SEQUENCE zoekt_repositories_id_seq
ALTER SEQUENCE zoekt_repositories_id_seq OWNED BY zoekt_repositories.id;
-CREATE TABLE zoekt_shards (
- id bigint NOT NULL,
- index_base_url text NOT NULL,
- search_base_url text NOT NULL,
- created_at timestamp with time zone NOT NULL,
- updated_at timestamp with time zone NOT NULL,
- uuid uuid DEFAULT '00000000-0000-0000-0000-000000000000'::uuid NOT NULL,
- last_seen_at timestamp with time zone DEFAULT '1970-01-01 00:00:00+00'::timestamp with time zone NOT NULL,
- used_bytes bigint DEFAULT 0 NOT NULL,
- total_bytes bigint DEFAULT 0 NOT NULL,
- metadata jsonb DEFAULT '{}'::jsonb NOT NULL,
- CONSTRAINT check_61794bac26 CHECK ((char_length(search_base_url) <= 1024)),
- CONSTRAINT check_c65bb85a32 CHECK ((char_length(index_base_url) <= 1024))
-);
-
-CREATE SEQUENCE zoekt_shards_id_seq
- START WITH 1
- INCREMENT BY 1
- NO MINVALUE
- NO MAXVALUE
- CACHE 1;
-
-ALTER SEQUENCE zoekt_shards_id_seq OWNED BY zoekt_shards.id;
-
CREATE SEQUENCE zoekt_tasks_id_seq
START WITH 1
INCREMENT BY 1
@@ -23151,8 +23127,6 @@ ALTER TABLE ONLY zoekt_replicas ALTER COLUMN id SET DEFAULT nextval('zoekt_repli
ALTER TABLE ONLY zoekt_repositories ALTER COLUMN id SET DEFAULT nextval('zoekt_repositories_id_seq'::regclass);
-ALTER TABLE ONLY zoekt_shards ALTER COLUMN id SET DEFAULT nextval('zoekt_shards_id_seq'::regclass);
-
ALTER TABLE ONLY zoom_meetings ALTER COLUMN id SET DEFAULT nextval('zoom_meetings_id_seq'::regclass);
ALTER TABLE ONLY analytics_cycle_analytics_issue_stage_events
@@ -26005,9 +25979,6 @@ ALTER TABLE ONLY zoekt_replicas
ALTER TABLE ONLY zoekt_repositories
ADD CONSTRAINT zoekt_repositories_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY zoekt_shards
- ADD CONSTRAINT zoekt_shards_pkey PRIMARY KEY (id);
-
ALTER TABLE ONLY zoekt_tasks
ADD CONSTRAINT zoekt_tasks_pkey PRIMARY KEY (id, partition_id);
@@ -31706,12 +31677,6 @@ CREATE INDEX index_zoekt_repositories_on_project_id ON zoekt_repositories USING
CREATE INDEX index_zoekt_repositories_on_state ON zoekt_repositories USING btree (state);
-CREATE UNIQUE INDEX index_zoekt_shards_on_index_base_url ON zoekt_shards USING btree (index_base_url);
-
-CREATE INDEX index_zoekt_shards_on_last_seen_at ON zoekt_shards USING btree (last_seen_at);
-
-CREATE UNIQUE INDEX index_zoekt_shards_on_search_base_url ON zoekt_shards USING btree (search_base_url);
-
CREATE INDEX index_zoekt_tasks_on_state ON ONLY zoekt_tasks USING btree (state);
CREATE INDEX index_zoekt_tasks_on_zoekt_node_id_and_state_and_perform_at ON ONLY zoekt_tasks USING btree (zoekt_node_id, state, perform_at);
@@ -31968,8 +31933,6 @@ CREATE UNIQUE INDEX unique_vuln_merge_request_link_vuln_id_and_mr_id ON vulnerab
CREATE UNIQUE INDEX unique_zoekt_enabled_namespaces_on_root_namespace_id ON zoekt_enabled_namespaces USING btree (root_namespace_id);
-CREATE UNIQUE INDEX unique_zoekt_shards_uuid ON zoekt_shards USING btree (uuid);
-
CREATE INDEX user_follow_users_followee_id_idx ON user_follow_users USING btree (followee_id);
CREATE UNIQUE INDEX virtual_reg_packages_maven_reg_upstreams_on_unique_reg_ids ON virtual_registries_packages_maven_registry_upstreams USING btree (registry_id);
diff --git a/doc/administration/gitaly/concurrency_limiting.md b/doc/administration/gitaly/concurrency_limiting.md
index 3bb27886348..d09c4b1928b 100644
--- a/doc/administration/gitaly/concurrency_limiting.md
+++ b/doc/administration/gitaly/concurrency_limiting.md
@@ -154,7 +154,7 @@ algorithm. Each adaptive limit:
This mechanism provides some headroom for the machine to "breathe" and speeds up current inflight requests.
-
+
The adaptive limiter calibrates the limits every 30 seconds and:
diff --git a/doc/administration/gitaly/configure_gitaly.md b/doc/administration/gitaly/configure_gitaly.md
index 94678b34dfd..1d754b2b8c2 100644
--- a/doc/administration/gitaly/configure_gitaly.md
+++ b/doc/administration/gitaly/configure_gitaly.md
@@ -99,7 +99,7 @@ The following list depicts the network architecture of Gitaly:
The following diagram illustrates communication between Gitaly servers and GitLab Rails showing
the default ports for HTTP and HTTPs communication.
-
+
WARNING:
Gitaly servers must not be exposed to the public internet as Gitaly network traffic is unencrypted
diff --git a/doc/administration/gitaly/img/gitaly_adaptive_concurrency_limit.png b/doc/administration/gitaly/img/gitaly_adaptive_concurrency_limit_v16_6.png
similarity index 100%
rename from doc/administration/gitaly/img/gitaly_adaptive_concurrency_limit.png
rename to doc/administration/gitaly/img/gitaly_adaptive_concurrency_limit_v16_6.png
diff --git a/doc/administration/gitaly/img/gitaly_network_13_9.png b/doc/administration/gitaly/img/gitaly_network_v13_9.png
similarity index 100%
rename from doc/administration/gitaly/img/gitaly_network_13_9.png
rename to doc/administration/gitaly/img/gitaly_network_v13_9.png
diff --git a/doc/administration/img/abuse_report_blocked_user.png b/doc/administration/img/abuse_report_blocked_user_v11_7.png
similarity index 100%
rename from doc/administration/img/abuse_report_blocked_user.png
rename to doc/administration/img/abuse_report_blocked_user_v11_7.png
diff --git a/doc/administration/img/kroki_c4_diagram.png b/doc/administration/img/kroki_c4_diagram_v13_7.png
similarity index 100%
rename from doc/administration/img/kroki_c4_diagram.png
rename to doc/administration/img/kroki_c4_diagram_v13_7.png
diff --git a/doc/administration/img/kroki_graphviz_diagram.png b/doc/administration/img/kroki_graphviz_diagram_v13_7.png
similarity index 100%
rename from doc/administration/img/kroki_graphviz_diagram.png
rename to doc/administration/img/kroki_graphviz_diagram_v13_7.png
diff --git a/doc/administration/img/kroki_nomnoml_diagram.png b/doc/administration/img/kroki_nomnoml_diagram_v13_7.png
similarity index 100%
rename from doc/administration/img/kroki_nomnoml_diagram.png
rename to doc/administration/img/kroki_nomnoml_diagram_v13_7.png
diff --git a/doc/administration/img/kroki_plantuml_diagram.png b/doc/administration/img/kroki_plantuml_diagram_v13_7.png
similarity index 100%
rename from doc/administration/img/kroki_plantuml_diagram.png
rename to doc/administration/img/kroki_plantuml_diagram_v13_7.png
diff --git a/doc/administration/integration/kroki.md b/doc/administration/integration/kroki.md
index 2308a51ddfe..b476004c7d8 100644
--- a/doc/administration/integration/kroki.md
+++ b/doc/administration/integration/kroki.md
@@ -116,7 +116,7 @@ The above blocks are converted to an HTML image tag with source pointing to the
Kroki instance. If the Kroki server is correctly configured, this should
render a nice diagram instead of the block:
-
+
Kroki supports more than a dozen diagram libraries. Here's a few examples for AsciiDoc:
@@ -147,7 +147,7 @@ digraph finite_state_machine {
....
```
-
+
**C4 (based on PlantUML)**
@@ -173,7 +173,7 @@ Rel(banking_system, mainframe, "Uses")
....
```
-
+
@@ -200,4 +200,4 @@ Rel(banking_system, mainframe, "Uses")
....
```
-
+
diff --git a/doc/administration/logs/img/network_monitor_xid.png b/doc/administration/logs/img/network_monitor_xid_v13_6.png
similarity index 100%
rename from doc/administration/logs/img/network_monitor_xid.png
rename to doc/administration/logs/img/network_monitor_xid_v13_6.png
diff --git a/doc/administration/logs/tracing_correlation_id.md b/doc/administration/logs/tracing_correlation_id.md
index 25bc3f74aef..ca8fcff42bf 100644
--- a/doc/administration/logs/tracing_correlation_id.md
+++ b/doc/administration/logs/tracing_correlation_id.md
@@ -44,7 +44,7 @@ To locate a relevant request and view its correlation ID:
See the following example:
-
+
### Getting the correlation ID from your logs
diff --git a/doc/administration/reference_architectures/index.md b/doc/administration/reference_architectures/index.md
index 78fa2c8deb8..e5dc904a6db 100644
--- a/doc/administration/reference_architectures/index.md
+++ b/doc/administration/reference_architectures/index.md
@@ -84,9 +84,9 @@ Finding out the RPS can depend notably on the specific environment setup and mon
If you can't determine your RPS, we provide an alternative sizing method based on equivalent User Count by Load Category. This count is mapped to typical RPS values, considering both manual and automated usage.
-#### Initial Sizing Guide
+#### Initial sizing guide
-See initial sizing guide table below for guidance on what architecture to pick for the expected load:
+To determine which architecture to pick for the expected load, see the following initial sizing guide table:
@@ -168,55 +168,52 @@ See initial sizing guide table below for guidance on what architecture to pick f
NOTE:
-Before selecting an initial Reference Architecture, we recommended reviewing this section thoroughly to consider other factors such as High Availability (HA) or the use of Large Monorepos, as these may impact the choice beyond just RPS or user count.
+Before you select an initial architecture, review this section thoroughly. Consider other factors such as High Availability (HA) or use of large monorepos, as they may impact the choice beyond just RPS or user count.
NOTE:
-After selecting an initial Reference Architecture, it's possible to then [scale up and down](#scaling-an-environment) accordingly to your needs if metrics support.
+After you select an initial reference architecture, you can [scale up and down](#scaling-an-environment) according to your needs if metrics support.
### Standalone (non-HA)
-For environments serving 2,000 or fewer users, we generally recommend a standalone approach by deploying a non-highly available single or multi-node environment. With this approach, you can employ strategies such as [automated backups](../../administration/backup_restore/backup_gitlab.md#configuring-cron-to-make-daily-backups) for recovery to provide a good level of RPO / RTO while avoiding the complexities that come with HA.
+For environments serving 2,000 or fewer users, we recommend a standalone approach by deploying a non-HA, single or multi-node environment. With this approach, you can employ strategies such as [automated backups](../../administration/backup_restore/backup_gitlab.md#configuring-cron-to-make-daily-backups) for recovery. These strategies provide a good level of recovery time objective (RPO) or recovery point objective (RTO) while avoiding the complexities that come with HA.
-*[RTO]: Recovery time objective
-*[RPO]: Recovery point objective
-
-With standalone setups, especially single node environments, there are [various options available for installation](../../install/index.md) and management including [the ability to deploy directly via select cloud provider marketplaces](https://page.gitlab.com/cloud-partner-marketplaces.html) that reduce the complexity a little further.
+With standalone setups, especially single node environments, various options are available for [installation](../../install/index.md) and management. The options include [the ability to deploy directly by using select cloud provider marketplaces](https://page.gitlab.com/cloud-partner-marketplaces.html) that reduce the complexity a little further.
### High Availability (HA)
High Availability ensures every component in the GitLab setup can handle failures through various mechanisms. However, to achieve this is complex, and the environments required can be sizable.
-For environments serving 3,000 or more users we generally recommend that a HA strategy is used as at this level outages have a bigger impact against more users. All the architectures in this range have HA built in by design for this reason.
+For environments serving 3,000 or more users, we generally recommend using an HA strategy. At this level, outages have a bigger impact against more users. All the architectures in this range have HA built in by design for this reason.
#### Do you need High Availability (HA)?
-As mentioned above, achieving HA does come at a cost. The environment requirements are sizable as each component needs to be multiplied, which comes with additional actual and maintenance costs.
+As mentioned previously, achieving HA comes at a cost. The environment requirements are sizable as each component needs to be multiplied, which comes with additional actual and maintenance costs.
-For a lot of our customers with fewer than 3,000 users, we've found a backup strategy is sufficient and even preferable. While this does have a slower recovery time, it also means you have a much smaller architecture and less maintenance costs as a result.
+For a lot of our customers with fewer than 3,000 users, we've found that a backup strategy is sufficient and even preferable. While this does have a slower recovery time, it also means you have a much smaller architecture and less maintenance costs as a result.
-In general then, we'd only recommend you employ HA in the following scenarios:
+As a general guideline, employ HA only in the following scenarios:
- When you have 3,000 or more users.
- When GitLab being down would critically impact your workflow.
-#### Scaled-down High Availability (HA) approaches
+#### Scaled-down High Availability (HA) approach
-If you still need to have HA for a lower number of users, this can be achieved with an adjusted [3K architecture](3k_users.md#supported-modifications-for-lower-user-counts-ha).
+If you still need HA for fewer users, you can achieve it with an adjusted [3K architecture](3k_users.md#supported-modifications-for-lower-user-counts-ha).
#### Zero-downtime upgrades
-[Zero-downtime upgrades](../../update/zero_downtime.md) are available for standard Reference Architecture environments with HA (Cloud Native Hybrid is [not supported](https://gitlab.com/groups/gitlab-org/cloud-native/-/epics/52)). This allows for an environment to stay up during an upgrade, but the process is more complex as a result and has some limitations as detailed in the documentation.
+[Zero-downtime upgrades](../../update/zero_downtime.md) are available for standard environments with HA (Cloud Native Hybrid is [not supported](https://gitlab.com/groups/gitlab-org/cloud-native/-/epics/52)). This allows for an environment to stay up during an upgrade. However, this process is more complex as a result and has some limitations as detailed in the documentation.
-When going through this process it's worth noting that there may still be brief moments of downtime when the HA mechanisms take effect.
+When going through this process, it's worth noting that there may still be brief moments of downtime when the HA mechanisms take effect.
-In most cases the downtime required for doing an upgrade shouldn't be substantial, so this is only recommended if it's a key requirement for you.
+In most cases, the downtime required for doing an upgrade shouldn't be substantial. Use this approach only if it's a key requirement for you.
### Cloud Native Hybrid (Kubernetes HA)
-As an additional layer of HA resilience you can deploy select components in Kubernetes, known as a Cloud Native Hybrid Reference Architecture. For stability
+As an additional layer of HA resilience, you can deploy select components in Kubernetes, known as a Cloud Native Hybrid reference architecture. For stability
reasons, stateful components such as Gitaly [cannot be deployed in Kubernetes](#stateful-components-in-kubernetes).
-This is an alternative and more **advanced** setup compared to a standard Reference Architecture. Running services in Kubernetes is well known to be complex. **This setup is only recommended** if you have strong working knowledge and experience in Kubernetes.
+Cloud Native Hybrid is an alternative and more **advanced** setup compared to a standard reference architecture. Running services in Kubernetes is complex. **Use this setup** only if you have strong working knowledge and experience in Kubernetes.
### GitLab Geo (Cross Regional Distribution / Disaster Recovery)
@@ -229,27 +226,27 @@ requires at least two separate environments:
If the primary site becomes unavailable, you can fail over to one of the secondary sites.
-This **advanced and complex** setup should only be undertaken if DR is
+Use this **advanced and complex** setup only if DR is
a key requirement for your environment. You must also make additional decisions
-on how each site is configured, such as if each secondary site would be the
-same architecture as the primary, or if each site is configured for HA.
+on how each site is configured. For example, if each secondary site would be the
+same architecture as the primary or if each site is configured for HA.
### Large monorepos / Additional workloads
-If you have any [large monorepos](#large-monorepos) or significant [additional workloads](#additional-workloads), these can affect the performance of the environment notably and adjustments may be required depending on the context.
+[Large monorepos](#large-monorepos) or significant [additional workloads](#additional-workloads) can affect the performance of the environment notably. Some adjustments may be required depending on the context.
-If either applies to you, it's encouraged for you to reach out to your [Customer Success Manager](https://handbook.gitlab.com/job-families/sales/customer-success-management/) or our [Support team](https://about.gitlab.com/support/)
+If this situation applies to you, reach out to your [Customer Success Manager](https://handbook.gitlab.com/job-families/sales/customer-success-management/) or our [Support team](https://about.gitlab.com/support/)
for further guidance.
### Cloud provider services
For all the previously described strategies, you can run select GitLab components on equivalent cloud provider services such as the PostgreSQL database or Redis.
-[For more information, see the recommended cloud providers and services](#recommended-cloud-providers-and-services).
+For more information, see the [recommended cloud providers and services](#recommended-cloud-providers-and-services).
### Decision Tree
-Below you can find the above guidance in the form of a decision tree. It's recommended you read through the above guidance in full first before though.
+Read through the above guidance in full first before you refer to the following decision tree.
```mermaid
%%{init: { 'theme': 'base' } }%%
@@ -296,75 +293,75 @@ linkStyle default fill:none,stroke:#7759C2
## Requirements
-Before implementing a reference architecture, refer to the following requirements and guidance.
+Before implementing a reference architecture, see the following requirements and guidance.
### Supported CPUs
-The reference architectures are built and tested across various cloud providers, primarily GCP and AWS, with
-CPU targets being the lowest common denominator to ensure the widest range of compatibility:
+The architectures are built and tested across various cloud providers, primarily GCP and AWS.
+To ensure the widest range of compatibility, CPU targets are intentionally set to the lowest common denominator across these platforms:
- The [`n1` series](https://cloud.google.com/compute/docs/general-purpose-machines#n1_machines) for GCP.
- The [`m5` series](https://aws.amazon.com/ec2/instance-types/) for AWS.
-Depending on other requirements such as memory or network bandwidth and cloud provider availability, different machine types are used accordingly throughout the architectures, but it is expected that the target CPUs above should perform well.
+Depending on other requirements such as memory or network bandwidth and cloud provider availability, different machine types are used accordingly throughout the architectures. We expect that the target CPUs above perform well.
If you want, you can select a newer machine type series and have improved performance as a result.
-Additionally, ARM CPUs are supported for Linux package environments and for any [Cloud Provider services](#cloud-provider-services) where applicable.
+Additionally, ARM CPUs are supported for Linux package environments and for any [cloud provider services](#cloud-provider-services).
NOTE:
Any "burstable" instance types are not recommended due to inconsistent performance.
### Supported disk types
-As a general guidance, most standard disk types are expected to work for GitLab, but be aware of the following specific call-outs:
+Most standard disk types are expected to work for GitLab. However, be aware of the following specific call-outs:
- [Gitaly](../gitaly/index.md#disk-requirements) requires at least 8,000 input/output operations per second (IOPS) for read operations, and 2,000 IOPS for write operations.
- We don't recommend the use of any disk types that are "burstable" due to inconsistent performance.
-Outside the above standard, disk types are expected to work for GitLab and the choice of each depends on your specific requirements around areas, such as durability or costs.
+Other disk types are expected to work with GitLab. Choose based on your requirements such as durability or cost.
### Supported infrastructure
-As a general guidance, GitLab should run on most infrastructure such as reputable Cloud Providers (AWS, GCP, Azure) and
+GitLab should run on most infrastructures such as reputable cloud providers (AWS, GCP, Azure) and
their services, or self-managed (ESXi) that meet both:
-- The specifications detailed in each reference architecture.
+- The specifications detailed in each architecture.
- Any requirements in this section.
-However, this does not constitute a guarantee for every potential permutation.
+However, this does not guarantee compatibility with every potential permutation.
See [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information.
### Large Monorepos
-The reference architectures were tested with repositories of varying sizes that follow best practices.
+The architectures were tested with repositories of varying sizes that follow best practices.
**However, [large monorepos](../../user/project/repository/monorepos/index.md) (several gigabytes or more) can significantly impact the performance of Git and in turn the environment itself.**
-Their presence, and how they are used, can put a significant strain on the entire system from Gitaly through to the underlying infrastructure.
+Their presence and how they are used can put a significant strain on the entire system from Gitaly to the underlying infrastructure.
The performance implications are largely software in nature. Additional hardware resources lead to diminishing returns.
WARNING:
-If this applies to you, we strongly recommended referring to the linked documentation and reaching out to your [Customer Success Manager](https://handbook.gitlab.com/job-families/sales/customer-success-management/) or our [Support team](https://about.gitlab.com/support/) for further guidance.
+If this applies to you, we strongly recommend you follow the linked documentation and reach out to your [Customer Success Manager](https://handbook.gitlab.com/job-families/sales/customer-success-management/) or our [Support team](https://about.gitlab.com/support/) for further guidance.
-As such, large monorepos come with notable cost. If you have such a repository we strongly recommend
-the following guidance is followed to ensure the best chance of good performance and to keep costs in check:
+Large monorepos come with notable cost. If you have such a repository,
+follow these guidance to ensure good performance and to keep costs in check:
- [Optimize the large monorepo](../../user/project/repository/monorepos/index.md#optimize-gitlab-settings). Using features such as
[LFS](../../user/project/repository/monorepos/index.md#use-lfs-for-large-blobs) to not store binaries, and other approaches for reducing repository size, can
dramatically improve performance and reduce costs.
-- Depending on the monorepo, increased environment specifications may be required to compensate. Gitaly in particular will likely require additional resources along with Praefect, GitLab Rails, and Load Balancers. This depends notably on the monorepo itself and the usage against it.
-- When the monorepo is significantly large (20 gigabytes or more) further additional strategies maybe required such as even further increased specifications or in some cases a separate Gitaly backend for the monorepo alone.
-- Network and disk bandwidth is another potential consideration with large monorepos. In very heavy cases, it's possible to see bandwidth saturation if there's a high amount of concurrent clones (such as with CI). It's strongly recommended [reducing full clones wherever possible](../../user/project/repository/monorepos/index.md#reduce-concurrent-clones-in-cicd) in this scenario. Otherwise, additional environment specifications may be required to increase bandwidth, but this differs between cloud providers.
+- Depending on the monorepo, increased environment specifications may be required to compensate. Gitaly might require additional resources along with Praefect, GitLab Rails, and Load Balancers. This depends on the monorepo itself and its usage.
+- When the monorepo is significantly large (20 gigabytes or more), further additional strategies may be required such as even further increased specifications or in some cases, a separate Gitaly backend for the monorepo alone.
+- Network and disk bandwidth is another potential consideration with large monorepos. In very heavy cases, bandwidth saturation is possible if there's a high amount of concurrent clones (such as with CI). [Reduce full clones wherever possible](../../user/project/repository/monorepos/index.md#reduce-concurrent-clones-in-cicd) in this scenario. Otherwise, additional environment specifications may be required to increase bandwidth. This differs based on cloud providers.
### Additional workloads
-These reference architectures have been [designed and tested](index.md#validation-and-test-results) for standard GitLab
+These architectures have been [designed and tested](index.md#validation-and-test-results) for standard GitLab
setups based on real data.
However, additional workloads can multiply the impact of operations by triggering follow-up actions.
-You may need to adjust the suggested specifications to compensate if you use, for example:
+You may need to adjust the suggested specifications to compensate if you use:
- Security software on the nodes.
- Hundreds of concurrent CI jobs for [large repositories](../../user/project/repository/monorepos/index.md).
@@ -373,48 +370,48 @@ You may need to adjust the suggested specifications to compensate if you use, fo
- [Server hooks](../server_hooks.md).
- [System hooks](../system_hooks.md).
-As a general rule, you should have robust monitoring in place to measure the impact of any additional workloads to
-inform any changes needed to be made. It's also strongly encouraged for you to reach out to your [Customer Success Manager](https://handbook.gitlab.com/job-families/sales/customer-success-management/) or our [Support team](https://about.gitlab.com/support/)
+Generally, you should have robust monitoring in place to measure the impact of any additional workloads to
+inform any changes needed to be made. Reach out to your [Customer Success Manager](https://handbook.gitlab.com/job-families/sales/customer-success-management/) or our [Support team](https://about.gitlab.com/support/)
for further guidance.
### Load Balancers
-The Reference Architectures make use of up to two Load Balancers depending on the class:
+The architectures make use of up to two load balancers depending on the class:
-- External Load Balancer - Serves traffic to any external facing components, primarily Rails.
-- Internal Load Balancer - Serves traffic to select internal components that have been deployed in an HA fashion such as Praefect or PgBouncer.
+- External load balancer - Serves traffic to any external facing components, primarily Rails.
+- Internal load balancer - Serves traffic to select internal components that are deployed in an HA fashion such as Praefect or PgBouncer.
The specifics on which load balancer to use, or its exact configuration is beyond the scope of GitLab documentation. The most common options
-are to set up load balancers on machine nodes or to use a service such as one offered by Cloud Providers. If deploying a Cloud Native Hybrid environment the Charts can handle the set-up of the External Load Balancer via Kubernetes Ingress.
+are to set up load balancers on machine nodes or to use a service such as one offered by cloud providers. If deploying a Cloud Native Hybrid environment, the charts can handle the external load balancer setup by using Kubernetes Ingress.
-For each Reference Architecture class a base machine size has given to help get you started if you elect to deploy directly on machines, but these may need to be adjusted accordingly depending on the load balancer used and amount of workload. Of note machines can have varying [network bandwidth](#network-bandwidth) that should also be taken into consideration.
+Each architecture class includes a recommended base machine size to deploy directly on machines. However, they may need adjustment based on factors such as the chosen load balancer and expected workload. Of note machines can have varying [network bandwidth](#network-bandwidth) that should also be taken into consideration.
-Note the following sections of additional guidance for Load Balancers.
+The following sections provide additional guidance for load balancers.
#### Balancing algorithm
-We recommend that a least-connection-based load balancing algorithm or equivalent is used wherever possible to ensure equal spread of calls to the nodes and good performance.
+To ensure equal spread of calls to the nodes and good performance, use a least-connection-based load balancing algorithm or equivalent wherever possible.
-We don’t recommend the use of round-robin algorithms as they are known to not spread connections equally in practice.
+We don't recommend the use of round-robin algorithms as they are known to not spread connections equally in practice.
#### Network Bandwidth
-The total network bandwidth available to a load balancer when deployed on a machine can vary notably across Cloud Providers. In particular some Cloud Providers, like [AWS](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-network-bandwidth.html), may operate on a burst system with credits to determine the bandwidth at any time.
+The total network bandwidth available to a load balancer when deployed on a machine can vary notably across cloud providers. Some cloud providers, like [AWS](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-network-bandwidth.html), may operate on a burst system with credits to determine the bandwidth at any time.
-The network bandwidth your environment's load balancers will require is dependent on numerous factors such as data shape and workload. The recommended base sizes for each Reference Architecture class have been selected based on real data but in some scenarios, such as consistent clones of [large monorepos](#large-monorepos), the sizes may need to be adjusted accordingly.
+The required network bandwidth for your load balancers depends on factors such as data shape and workload. The recommended base sizes for each architecture class have been selected based on real data. However, in some scenarios such as consistent clones of [large monorepos](#large-monorepos), the sizes may need to be adjusted accordingly.
### No swap
Swap is not recommended in the reference architectures. It's a failsafe that impacts performance greatly. The
-reference architectures are designed to have enough memory in most cases to avoid needing swap.
+architectures are designed to have enough memory in most cases to avoid the need for swap.
### Praefect PostgreSQL
[Praefect requires its own database server](../gitaly/praefect.md#postgresql) and
-that to achieve full High Availability, a third-party PostgreSQL database solution is required.
+a third-party PostgreSQL database solution to achieve full HA.
-We hope to offer a built-in solution for these restrictions in the future. In the meantime, a non-HA PostgreSQL server
-can be set up using the Linux package as the specifications reflect. Refer to the following issues for more information:
+We hope to offer a built-in solution for these restrictions in the future. In the meantime, you can set up a
+non-HA PostgreSQL server using the Linux package as the specifications reflect. See the following issues for more information:
- [`omnibus-gitlab#7292`](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/7292).
- [`gitaly#3398`](https://gitlab.com/gitlab-org/gitaly/-/issues/3398).
diff --git a/doc/administration/review_abuse_reports.md b/doc/administration/review_abuse_reports.md
index 33ca88bdc0d..7821e5e9ce0 100644
--- a/doc/administration/review_abuse_reports.md
+++ b/doc/administration/review_abuse_reports.md
@@ -83,7 +83,7 @@ After blocking, you can still either:
The following is an example of a blocked user listed on the **Abuse reports**
page:
-
+
## Related topics
diff --git a/doc/administration/settings/img/file_template_user_dropdown.png b/doc/administration/settings/img/file_template_user_dropdown_v11_4.png
similarity index 100%
rename from doc/administration/settings/img/file_template_user_dropdown.png
rename to doc/administration/settings/img/file_template_user_dropdown_v11_4.png
diff --git a/doc/administration/settings/img/rate_limits_on_raw_endpoints.png b/doc/administration/settings/img/rate_limits_on_raw_endpoints_v12_2.png
similarity index 100%
rename from doc/administration/settings/img/rate_limits_on_raw_endpoints.png
rename to doc/administration/settings/img/rate_limits_on_raw_endpoints_v12_2.png
diff --git a/doc/administration/settings/img/sign_up_terms.png b/doc/administration/settings/img/sign_up_terms_v11_0.png
similarity index 100%
rename from doc/administration/settings/img/sign_up_terms.png
rename to doc/administration/settings/img/sign_up_terms_v11_0.png
diff --git a/doc/administration/settings/img/two_factor_grace_period.png b/doc/administration/settings/img/two_factor_grace_period_v12_5.png
similarity index 100%
rename from doc/administration/settings/img/two_factor_grace_period.png
rename to doc/administration/settings/img/two_factor_grace_period_v12_5.png
diff --git a/doc/administration/settings/img/update-available.png b/doc/administration/settings/img/update_available_v10_6.png
similarity index 100%
rename from doc/administration/settings/img/update-available.png
rename to doc/administration/settings/img/update_available_v10_6.png
diff --git a/doc/administration/settings/instance_template_repository.md b/doc/administration/settings/instance_template_repository.md
index 6c5d1bc100b..2e3bccc85f5 100644
--- a/doc/administration/settings/instance_template_repository.md
+++ b/doc/administration/settings/instance_template_repository.md
@@ -69,7 +69,7 @@ extension and not be empty. So, the hierarchy should look like this:
Your custom templates are displayed on the dropdown list when a new file is added through the GitLab UI:
-
+
If this feature is disabled or no templates are present,
no **Custom** section displays in the selection dropdown list.
diff --git a/doc/administration/settings/rate_limits_on_raw_endpoints.md b/doc/administration/settings/rate_limits_on_raw_endpoints.md
index 7e98941b1b1..5332c4c3159 100644
--- a/doc/administration/settings/rate_limits_on_raw_endpoints.md
+++ b/doc/administration/settings/rate_limits_on_raw_endpoints.md
@@ -18,7 +18,7 @@ This setting defaults to `300` requests per minute, and allows you to rate limit
For example, requests over `300` per minute to `https://gitlab.com/gitlab-org/gitlab-foss/raw/master/app/controllers/application_controller.rb` are blocked. Access to the raw file is released after 1 minute.
-
+
This limit is:
diff --git a/doc/administration/settings/sign_in_restrictions.md b/doc/administration/settings/sign_in_restrictions.md
index e26571c5353..183cc89681b 100644
--- a/doc/administration/settings/sign_in_restrictions.md
+++ b/doc/administration/settings/sign_in_restrictions.md
@@ -167,7 +167,7 @@ After the two-factor authentication is configured as mandatory, users are allowe
to skip forced configuration of two-factor authentication for the configurable grace
period in hours.
-
+
## Email notification for unknown sign-ins
diff --git a/doc/administration/settings/sign_up_restrictions.md b/doc/administration/settings/sign_up_restrictions.md
index d0b3cfcf63e..5cae04fbd9e 100644
--- a/doc/administration/settings/sign_up_restrictions.md
+++ b/doc/administration/settings/sign_up_restrictions.md
@@ -258,13 +258,13 @@ See the [documentation on setting up an LDAP user filter](../auth/ldap/index.md#
DETAILS:
**Tier:** Ultimate
**Offering:** Self-managed, GitLab Dedicated
+**Status:** Beta
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/433166) in GitLab 16.9 [with a flag](../feature_flags.md) named `member_promotion_management`.
+> - Feature flag `member_promotion_management` [changed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/167757/) from `wip` to `beta` and enabled by default in GitLab 17.5.
FLAG:
The availability of this feature is controlled by a feature flag.
-For more information, see the history.
-This feature is available for testing, but not ready for production use.
In the **Ultimate** tier, [non billable roles](../../subscriptions/gitlab_com/index.md#billable-users), can be promoted to a billable role in any Project or Group, resulting in the increase of billable seats, without admins having any control on this promotion.
To prevent existing users of the subscription from being promoted to a billable role, you can enable role promotion approval.
diff --git a/doc/administration/settings/terms.md b/doc/administration/settings/terms.md
index ea606b8e048..25d915820cf 100644
--- a/doc/administration/settings/terms.md
+++ b/doc/administration/settings/terms.md
@@ -39,7 +39,7 @@ If an authenticated user declines the terms, they are signed out.
When enabled, it adds a mandatory checkbox to the sign up page for new users:
-
+