diff --git a/.eslintrc.yml b/.eslintrc.yml index 8556142eb3a..20215977ae3 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -127,8 +127,8 @@ rules: - selector: TemplateLiteral[expressions.0.name=DOCS_URL] > TemplateElement[value.cooked=/\u002Fjh|\u002Fee/] message: '`/ee` or `/jh` path found in docs url, use `DOCS_URL_IN_EE_DIR` in `jh_else_ce/lib/utils/url_utility`' # This can be removed once GitLab is on Vue 3 - - selector: MemberExpression[object.type='ThisExpression'][property.name='$delete'] - message: "$delete is not supported in Vue 3" + - selector: MemberExpression[object.type='ThisExpression'][property.name=/(\$delete|\$set)/] + message: "Vue 2's set/delete methods are not available in Vue 3. Create/assign new objects with the desired properties instead." no-restricted-properties: - error - object: window @@ -137,11 +137,19 @@ rules: # This can be removed once GitLab is on Vue 3 - object: vm property: $delete - message: '$delete is not supported in Vue 3' + message: "Vue 2's set/delete methods are not available in Vue 3. Create/assign new objects with the desired properties instead." # This can be removed once GitLab is on Vue 3 - object: Vue property: delete - message: 'delete is not supported in Vue 3' + message: "Vue 2's set/delete methods are not available in Vue 3. Create/assign new objects with the desired properties instead." + # This can be removed once GitLab is on Vue 3 + - object: vm + property: $set + message: "Vue 2's set/delete methods are not available in Vue 3. Create/assign new objects with the desired properties instead." + # This can be removed once GitLab is on Vue 3 + - object: Vue + property: set + message: "Vue 2's set/delete methods are not available in Vue 3. Create/assign new objects with the desired properties instead." no-restricted-imports: - error - paths: @@ -208,14 +216,18 @@ overrides: - selector: TemplateLiteral[expressions.0.name=DOCS_URL] > TemplateElement[value.cooked=/\u002Fjh|\u002Fee/] message: '`/ee` or `/jh` path found in docs url, use `DOCS_URL_IN_EE_DIR` in `jh_else_ce/lib/utils/url_utility`' # This can be removed once GitLab is on Vue 3 - - selector: CallExpression[callee.property.name="$delete"] - message: "$delete is restricted from being used. $delete is not supported in Vue 3" + - selector: CallExpression[callee.property.name=/(\$delete|\$set)/] + message: "Vue 2's set/delete methods are not available in Vue 3. Create/assign new objects with the desired properties instead." no-restricted-properties: - error # This can be removed once GitLab is on Vue 3 - object: Vue property: delete - message: 'delete is not supported in Vue 3' + message: "Vue 2's set/delete methods are not available in Vue 3. Create/assign new objects with the desired properties instead." + # This can be removed once GitLab is on Vue 3 + - object: Vue + property: set + message: "Vue 2's set/delete methods are not available in Vue 3. Create/assign new objects with the desired properties instead." no-unsanitized/method: off no-unsanitized/property: off local-rules/require-valid-help-page-path: off diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js index f56e9b8781d..3ad97819bce 100644 --- a/app/assets/javascripts/merge_request_tabs.js +++ b/app/assets/javascripts/merge_request_tabs.js @@ -433,18 +433,20 @@ export default class MergeRequestTabs { setCurrentAction(action) { this.currentAction = action; + const pathname = location.pathname.replace(/\/*$/, ''); + // Remove a trailing '/commits' '/diffs' '/pipelines' - let newState = location.pathname.replace(this.actionRegex, ''); + let newStatePathname = pathname.replace(this.actionRegex, ''); // Append the new action if we're on a tab other than 'notes' if (this.currentAction !== 'show' && this.currentAction !== 'new') { - newState += `/${this.currentAction}`; + newStatePathname += `/${this.currentAction}`; } // Ensure parameters and hash come along for the ride - newState += location.search + location.hash; + const newState = newStatePathname + location.search + location.hash; - if (window.location.pathname !== newState) { + if (pathname !== newStatePathname) { window.history.pushState( { url: newState, diff --git a/app/models/email.rb b/app/models/email.rb index be64880c3e8..a61e62011a2 100644 --- a/app/models/email.rb +++ b/app/models/email.rb @@ -14,6 +14,7 @@ class Email < ApplicationRecord scope :unconfirmed, -> { where(confirmed_at: nil) } scope :unconfirmed_and_created_before, ->(created_cut_off) { unconfirmed.where('created_at < ?', created_cut_off) } + before_save :detumble_email!, if: ->(email) { email.email_changed? } after_commit :update_invalid_gpg_signatures, if: -> { previous_changes.key?('confirmed_at') } devise :confirmable @@ -49,4 +50,10 @@ class Email < ApplicationRecord def primary_email_of_another_user? User.where(email: email).where.not(id: user_id).exists? end + + def detumble_email! + return unless Feature.enabled?(:store_detumbled_email, user, type: :gitlab_com_derisk) + + self.detumbled_email = ::Gitlab::Utils::Email.normalize_email(email) + end end diff --git a/app/views/groups/_create_chat_team.html.haml b/app/views/groups/_create_chat_team.html.haml index 45561031083..ce75043dbf6 100644 --- a/app/views/groups/_create_chat_team.html.haml +++ b/app/views/groups/_create_chat_team.html.haml @@ -4,7 +4,7 @@ .form-group .col-sm-2.col-form-label = f.label :create_chat_team do - %span.gl-display-flex + %span.gl-flex = custom_icon('icon_mattermost') %span.gl-ml-2= _('Mattermost') .col-sm-12 diff --git a/app/views/groups/_home_panel.html.haml b/app/views/groups/_home_panel.html.haml index 18349028dbd..9cd0a3411b6 100644 --- a/app/views/groups/_home_panel.html.haml +++ b/app/views/groups/_home_panel.html.haml @@ -4,8 +4,8 @@ .group-home-panel .gl-flex.gl-justify-between.gl-flex-wrap.gl-flex-col.sm:gl-flex-row.gl-gap-3.gl-my-5 - .home-panel-title-row.gl-display-flex - = render Pajamas::AvatarComponent.new(@group, alt: @group.name, size: 48, class: 'float-none gl-align-self-start gl-flex-shrink-0 gl-mr-3', avatar_options: { itemprop: 'logo' }) + .home-panel-title-row.gl-flex + = render Pajamas::AvatarComponent.new(@group, alt: @group.name, size: 48, class: 'float-none gl-self-start gl-shrink-0 gl-mr-3', avatar_options: { itemprop: 'logo' }) %h1.home-panel-title.gl-heading-1.gl-flex.gl-items-center.gl-flex-wrap.gl-gap-3.gl-break-anywhere.gl-mb-0{ itemprop: 'name' } = @group.name %span.visibility-icon.gl-text-subtle.has-tooltip{ data: { container: 'body' }, title: visibility_icon_description(@group) } @@ -20,12 +20,12 @@ .js-vue-notification-dropdown{ data: { disabled: emails_disabled.to_s, dropdown_items: notification_dropdown_items(@notification_setting).to_json, notification_level: @notification_setting.level, help_page_path: help_page_path('user/profile/notifications'), group_id: @group.id, container_class: 'gl-align-top' } } - if can_create_subgroups .sm:gl-w-auto.gl-w-full - = render Pajamas::ButtonComponent.new(href: new_group_path(parent_id: @group.id, anchor: 'create-group-pane'), button_options: { data: { testid: 'new-subgroup-button' }, class: 'gl-sm-w-auto gl-w-full'}) do + = render Pajamas::ButtonComponent.new(href: new_group_path(parent_id: @group.id, anchor: 'create-group-pane'), button_options: { data: { testid: 'new-subgroup-button' }, class: 'sm:gl-w-auto gl-w-full'}) do = _("New subgroup") - if can_create_projects .sm:gl-w-auto.gl-w-full - = render Pajamas::ButtonComponent.new(href: new_project_path(namespace_id: @group.id), variant: :confirm, button_options: { data: { testid: 'new-project-button' }, class: 'gl-sm-w-auto gl-w-full' }) do + = render Pajamas::ButtonComponent.new(href: new_project_path(namespace_id: @group.id), variant: :confirm, button_options: { data: { testid: 'new-project-button' }, class: 'sm:gl-w-auto gl-w-full' }) do = _('New project') = render 'groups/more_actions_dropdown', source: @group diff --git a/app/views/groups/_personalize.html.haml b/app/views/groups/_personalize.html.haml index 2f55aefb817..a644c67b12c 100644 --- a/app/views/groups/_personalize.html.haml +++ b/app/views/groups/_personalize.html.haml @@ -13,10 +13,10 @@ .row .form-group.col-sm-4 = f.label :setup_for_company, _('Who will be using this group?') - .gl-display-flex.gl-flex-direction-column.gl-lg-flex-direction-row - .gl-flex-grow-1.gl-display-flex.gl-align-items-center + .gl-flex.gl-flex-col.lg:gl-flex-row + .gl-grow.gl-flex.gl-items-center = f.gitlab_ui_radio_component :setup_for_company, true, _('My company or team') - .gl-flex-grow-1.gl-display-flex.gl-align-items-center + .gl-grow.gl-flex.gl-items-center = f.gitlab_ui_radio_component :setup_for_company, false, _('Just me') .row diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml index d51e28e84fd..87ba30b8835 100644 --- a/app/views/groups/group_members/index.html.haml +++ b/app/views/groups/group_members/index.html.haml @@ -3,7 +3,7 @@ .row.gl-mt-3 .col-lg-12 - .gl-display-flex.gl-flex-wrap.gl-justify-content-space-between + .gl-flex.gl-flex-wrap.gl-justify-between - if can_admin_group_member?(@group) %h4 = _('Group members') @@ -13,12 +13,12 @@ - if current_appearance&.member_guidelines? .gl-w-full.order-md-1 = brand_member_guidelines - .gl-display-flex.gl-flex-wrap.gl-align-items-center.gl-gap-3.gl-md-w-auto.gl-w-full - .js-invite-group-trigger{ data: { classes: 'gl-md-w-auto gl-w-full', display_text: _('Invite a group') } } + .gl-flex.gl-flex-wrap.gl-items-center.gl-gap-3.md:gl-w-auto.gl-w-full + .js-invite-group-trigger{ data: { classes: 'md:gl-w-auto gl-w-full', display_text: _('Invite a group') } } - if can_admin_service_accounts?(@group) = render_if_exists 'groups/group_members/create_service_account' .js-invite-members-trigger{ data: { variant: 'confirm', - classes: 'gl-md-w-auto gl-w-full', + classes: 'md:gl-w-auto gl-w-full', trigger_source: 'group_members_page', display_text: _('Invite members') } } = render 'groups/invite_groups_modal', group: @group, reload_page_on_submit: true diff --git a/app/views/groups/labels/edit.html.haml b/app/views/groups/labels/edit.html.haml index 34c7d0de0bb..558e303fca4 100644 --- a/app/views/groups/labels/edit.html.haml +++ b/app/views/groups/labels/edit.html.haml @@ -3,7 +3,7 @@ - page_title _("Edit"), @label.name, _("Labels") - show_lock_on_merge = @group.supports_lock_on_merge? -%h1.page-title.gl-font-size-h-display +%h1.page-title.gl-text-size-h-display = _('Edit label') = render 'shared/labels/form', url: group_label_path(@group, @label), back_path: @previous_labels_path, show_lock_on_merge: show_lock_on_merge diff --git a/app/views/groups/labels/new.html.haml b/app/views/groups/labels/new.html.haml index b8d89085d63..8e00ce53437 100644 --- a/app/views/groups/labels/new.html.haml +++ b/app/views/groups/labels/new.html.haml @@ -2,7 +2,7 @@ - breadcrumb_title _("New label") - page_title _("New Label") -%h1.page-title.gl-font-size-h-display +%h1.page-title.gl-text-size-h-display = _('New Label') = render 'shared/labels/form', url: group_labels_path, back_path: @previous_labels_path diff --git a/app/views/groups/milestones/edit.html.haml b/app/views/groups/milestones/edit.html.haml index bde7ec15994..c4a795ca1a8 100644 --- a/app/views/groups/milestones/edit.html.haml +++ b/app/views/groups/milestones/edit.html.haml @@ -3,7 +3,7 @@ - render "header_title" -%h1.page-title.gl-font-size-h-display +%h1.page-title.gl-text-size-h-display = _('Edit milestone') = render "form" diff --git a/app/views/groups/milestones/new.html.haml b/app/views/groups/milestones/new.html.haml index f817beebe0f..5971d165443 100644 --- a/app/views/groups/milestones/new.html.haml +++ b/app/views/groups/milestones/new.html.haml @@ -2,7 +2,7 @@ - breadcrumb_title _("New milestone") - page_title _("Milestones"), @milestone.name, _("Milestones") -%h1.page-title.gl-font-size-h-display +%h1.page-title.gl-text-size-h-display = _("New Milestone") .gl-mt-3 diff --git a/app/views/groups/projects.html.haml b/app/views/groups/projects.html.haml index 5a0dcf02256..c9275edb650 100644 --- a/app/views/groups/projects.html.haml +++ b/app/views/groups/projects.html.haml @@ -14,9 +14,9 @@ - c.with_body do %ul.content-list - @projects.each do |project| - %li.project-row.gl-align-items-center{ class: 'gl-display-flex!' } - = render Pajamas::AvatarComponent.new(project, alt: project.name, size: 48, class: 'gl-flex-shrink-0 gl-mr-5') - .gl-min-w-0.gl-flex-grow-1 + %li.project-row.gl-items-center{ class: '!gl-flex' } + = render Pajamas::AvatarComponent.new(project, alt: project.name, size: 48, class: 'gl-shrink-0 gl-mr-5') + .gl-min-w-0.gl-grow .title.gl-mr-5 = link_to project_path(project), class: 'js-prefetch-document' do %span.project-full-name @@ -34,9 +34,9 @@ = render 'shared/projects/badges', project: project, css_class: 'gl-mr-3' - .stats.gl-text-secondary.gl-flex-shrink-0.gl-hidden.sm:gl-flex.gl-gap-3 + .stats.gl-text-secondary.gl-shrink-0.gl-hidden.sm:gl-flex.gl-gap-3 = gl_badge_tag storage_counter(project.statistics&.storage_size) - .controls.gl-flex-shrink-0.gl-ml-5 + .controls.gl-shrink-0.gl-ml-5 = render Pajamas::ButtonComponent.new(href: project_project_members_path(project), variant: :link, button_options: { class: 'gl-mr-2' }) do diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml index e5b62254f49..b2022f9ae8e 100644 --- a/app/views/groups/show.html.haml +++ b/app/views/groups/show.html.haml @@ -6,7 +6,7 @@ - if show_invite_banner?(@group) = content_for :group_invite_members_banner do - .container-fluid.container-limited{ class: "gl-pb-2! gl-pt-6! #{@content_class}" } + .container-fluid.container-limited{ class: "!gl-pb-2 !gl-pt-6 #{@content_class}" } .js-group-invite-members-banner{ data: { svg_path: image_path('illustrations/add-user-sm.svg'), track_label: 'invite_members_banner', invite_members_path: group_group_members_path(@group), diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml index 852eec4fc20..ce1c40d52de 100644 --- a/app/views/help/index.html.haml +++ b/app/views/help/index.html.haml @@ -38,7 +38,7 @@ .card-header = _('Quick help') %ul.content-list - %li= link_to _('See our website for help'), support_url, { class: 'gl-text-blue-600!' } + %li= link_to _('See our website for help'), support_url, { class: '!gl-text-blue-600' } %li %button.btn-blank.btn-link.gl-button.js-trigger-search-bar{ type: 'button' } = _('Use the search bar on the top of this page') @@ -46,5 +46,5 @@ %button.btn-blank.btn-link.gl-button.js-trigger-shortcut{ type: 'button' } = _('Use shortcuts') - unless Gitlab::CurrentSettings.help_page_hide_commercial_content? - %li= link_to _('Get a support subscription'), "#{ApplicationHelper.promo_url}/pricing/", { class: 'gl-text-blue-600!' } - %li= link_to _('Compare GitLab editions'), "#{ApplicationHelper.promo_url}/features/#compare", { class: 'gl-text-blue-600!' } + %li= link_to _('Get a support subscription'), "#{ApplicationHelper.promo_url}/pricing/", { class: '!gl-text-blue-600' } + %li= link_to _('Compare GitLab editions'), "#{ApplicationHelper.promo_url}/features/#compare", { class: '!gl-text-blue-600' } diff --git a/app/views/help/instance_configuration.html.haml b/app/views/help/instance_configuration.html.haml index 416142b9e8c..00f2229cbc2 100644 --- a/app/views/help/instance_configuration.html.haml +++ b/app/views/help/instance_configuration.html.haml @@ -1,5 +1,5 @@ - page_title _('Instance Configuration') -.md.gl-font-lg.gl-mt-3 +.md.gl-text-lg.gl-mt-3 %h1= _('Instance Configuration') %p diff --git a/app/views/help/show.html.haml b/app/views/help/show.html.haml index 39f45e8b649..2720f482181 100644 --- a/app/views/help/show.html.haml +++ b/app/views/help/show.html.haml @@ -1,5 +1,5 @@ - page_title @path.split("/").reverse.map(&:humanize) - @content_class = "limit-container-width" unless fluid_layout -.md.gl-font-lg.gl-mt-3 +.md.gl-text-lg.gl-mt-3 = markdown @markdown diff --git a/app/views/import/bitbucket/status.html.haml b/app/views/import/bitbucket/status.html.haml index 5b9676c62c3..533f8041e22 100644 --- a/app/views/import/bitbucket/status.html.haml +++ b/app/views/import/bitbucket/status.html.haml @@ -1,8 +1,8 @@ - page_title _('Bitbucket import') - header_title _('Projects'), root_path -%h1.page-title.gl-font-size-h-display.gl-flex.gl-items-center - .gl-flex.gl-items-center.gl-justify-content-center +%h1.page-title.gl-text-size-h-display.gl-flex.gl-items-center + .gl-flex.gl-items-center.gl-justify-center = sprite_icon('bitbucket', css_class: 'gl-mr-3', size: 48) = _('Import projects from Bitbucket') diff --git a/app/views/import/bitbucket_server/new.html.haml b/app/views/import/bitbucket_server/new.html.haml index f4e3823b0a7..22b57ea553e 100644 --- a/app/views/import/bitbucket_server/new.html.haml +++ b/app/views/import/bitbucket_server/new.html.haml @@ -2,8 +2,8 @@ - header_title _("New project"), new_project_path - add_to_breadcrumbs s_('ProjectsNew|Import project'), new_project_path(anchor: 'import_project') -%h1.page-title.gl-font-size-h-display.gl-flex.gl-items-center - .gl-flex.gl-items-center.gl-justify-content-center +%h1.page-title.gl-text-size-h-display.gl-flex.gl-items-center + .gl-flex.gl-items-center.gl-justify-center = sprite_icon('bitbucket', css_class: 'gl-mr-3', size: 48) = _('Import repositories from Bitbucket Server') %hr diff --git a/app/views/import/bitbucket_server/status.html.haml b/app/views/import/bitbucket_server/status.html.haml index 665168c571f..a8cea9c415c 100644 --- a/app/views/import/bitbucket_server/status.html.haml +++ b/app/views/import/bitbucket_server/status.html.haml @@ -1,7 +1,7 @@ - page_title _('Bitbucket Server import') -%h1.page-title.gl-font-size-h-display.gl-flex.gl-items-center - .gl-flex.gl-items-center.gl-justify-content-center +%h1.page-title.gl-text-size-h-display.gl-flex.gl-items-center + .gl-flex.gl-items-center.gl-justify-center = sprite_icon('bitbucket', css_class: 'gl-mr-3', size: 48) = _('Import projects from Bitbucket Server') diff --git a/app/views/import/fogbugz/new.html.haml b/app/views/import/fogbugz/new.html.haml index cf17bdd3ee4..f05d7be6dbd 100644 --- a/app/views/import/fogbugz/new.html.haml +++ b/app/views/import/fogbugz/new.html.haml @@ -2,8 +2,8 @@ - header_title _("New project"), new_project_path - add_to_breadcrumbs s_('ProjectsNew|Import project'), new_project_path(anchor: 'import_project') -%h1.page-title.gl-font-size-h-display.gl-flex.gl-items-center - .gl-flex.gl-items-center.gl-justify-content-center +%h1.page-title.gl-text-size-h-display.gl-flex.gl-items-center + .gl-flex.gl-items-center.gl-justify-center = sprite_icon('bug', css_class: 'gl-mr-3', size: 48) = _('Import projects from FogBugz') %hr diff --git a/app/views/import/fogbugz/new_user_map.html.haml b/app/views/import/fogbugz/new_user_map.html.haml index 85f411f4515..a729d0aa043 100644 --- a/app/views/import/fogbugz/new_user_map.html.haml +++ b/app/views/import/fogbugz/new_user_map.html.haml @@ -2,8 +2,8 @@ - header_title _("New project"), new_project_path - add_to_breadcrumbs s_('ProjectsNew|Import project'), new_project_path(anchor: 'import_project') -%h1.page-title.gl-font-size-h-display.gl-flex - .gl-flex.gl-items-center.gl-justify-content-center +%h1.page-title.gl-text-size-h-display.gl-flex + .gl-flex.gl-items-center.gl-justify-center = sprite_icon('bug', css_class: 'gl-mr-2') = _('Import projects from FogBugz') %hr diff --git a/app/views/import/fogbugz/status.html.haml b/app/views/import/fogbugz/status.html.haml index 9371e485399..42f54097db3 100644 --- a/app/views/import/fogbugz/status.html.haml +++ b/app/views/import/fogbugz/status.html.haml @@ -1,6 +1,6 @@ - page_title _("FogBugz import") -%h1.page-title.gl-font-size-h-display.gl-flex.gl-items-center - .gl-flex.gl-items-center.gl-justify-content-center +%h1.page-title.gl-text-size-h-display.gl-flex.gl-items-center + .gl-flex.gl-items-center.gl-justify-center = sprite_icon('bug', css_class: 'gl-mr-3', size: 48) = _('Import projects from FogBugz') diff --git a/app/views/import/gitea/new.html.haml b/app/views/import/gitea/new.html.haml index 9bc7855fe54..caed978b396 100644 --- a/app/views/import/gitea/new.html.haml +++ b/app/views/import/gitea/new.html.haml @@ -2,8 +2,8 @@ - header_title _("New project"), new_project_path - add_to_breadcrumbs s_('ProjectsNew|Import project'), new_project_path(anchor: 'import_project') -%h1.page-title.gl-font-size-h-display.gl-flex.gl-items-center - .gl-flex.gl-items-center.gl-justify-content-center +%h1.page-title.gl-text-size-h-display.gl-flex.gl-items-center + .gl-flex.gl-items-center.gl-justify-center = sprite_icon('gitea', css_class: 'gl-mr-3', size: 48) = _('Import projects from Gitea') %hr diff --git a/app/views/import/gitea/status.html.haml b/app/views/import/gitea/status.html.haml index 8aa429c744c..dd001e02b13 100644 --- a/app/views/import/gitea/status.html.haml +++ b/app/views/import/gitea/status.html.haml @@ -1,6 +1,6 @@ - page_title _("Gitea import") -%h1.page-title.gl-font-size-h-display.gl-flex.gl-items-center - .gl-flex.gl-items-center.gl-justify-content-center +%h1.page-title.gl-text-size-h-display.gl-flex.gl-items-center + .gl-flex.gl-items-center.gl-justify-center = sprite_icon('gitea', css_class: 'gl-mr-3', size: 48) = _('Import projects from Gitea') diff --git a/app/views/import/github/new.html.haml b/app/views/import/github/new.html.haml index 7c4931db3be..21ec14eba49 100644 --- a/app/views/import/github/new.html.haml +++ b/app/views/import/github/new.html.haml @@ -4,7 +4,7 @@ - add_to_breadcrumbs s_('ProjectsNew|Import project'), new_project_path(anchor: 'import_project') .gl-border-solid.gl-border-gray-100.gl-border-0.gl-border-b-1 - %h1.gl-font-size-h1.gl-my-0.gl-py-4.gl-display-flex.gl-align-items-center.gl-gap-3 + %h1.gl-text-size-h1.gl-my-0.gl-py-4.gl-flex.gl-items-center.gl-gap-3 = sprite_icon('github', size: 24) %span= title @@ -46,7 +46,7 @@ - docs_link_tag_pair = tag_pair(docs_link, :link_start, :link_end) = safe_format(s_('GithubImport|%{link_start}Learn more%{link_end}.'), docs_link_tag_pair) - .form-actions.gl-display-flex.gl-justify-content-end + .form-actions.gl-flex.gl-justify-end = render Pajamas::ButtonComponent.new(href: new_project_path) do = _('Cancel') = render Pajamas::ButtonComponent.new(variant: :confirm, type: :submit, button_options: { class: 'gl-ml-3', data: { testid: 'authenticate-button' } }) do diff --git a/app/views/import/github/status.html.haml b/app/views/import/github/status.html.haml index 0f56ae92557..2b3250d213c 100644 --- a/app/views/import/github/status.html.haml +++ b/app/views/import/github/status.html.haml @@ -2,7 +2,7 @@ - page_title title .gl-border-solid.gl-border-gray-100.gl-border-0.gl-border-b-1 - %h1.gl-font-size-h1.gl-my-0.gl-py-4.gl-display-flex.gl-align-items-center.gl-gap-3 + %h1.gl-text-size-h1.gl-my-0.gl-py-4.gl-flex.gl-items-center.gl-gap-3 = sprite_icon('github', size: 24) %span= _('Import repositories from GitHub') diff --git a/app/views/import/gitlab/status.html.haml b/app/views/import/gitlab/status.html.haml index dbeef413d1c..841ece589eb 100644 --- a/app/views/import/gitlab/status.html.haml +++ b/app/views/import/gitlab/status.html.haml @@ -1,5 +1,5 @@ - page_title _("GitLab.com import") -%h1.page-title.gl-font-size-h-display +%h1.page-title.gl-text-size-h-display = sprite_icon('heart', css_class: 'gl-align-middle') = _('Import projects from GitLab.com') diff --git a/app/views/import/gitlab_projects/new.html.haml b/app/views/import/gitlab_projects/new.html.haml index 5561f743391..fdae847e68b 100644 --- a/app/views/import/gitlab_projects/new.html.haml +++ b/app/views/import/gitlab_projects/new.html.haml @@ -2,8 +2,8 @@ - header_title _("New project"), new_project_path - add_to_breadcrumbs s_('ProjectsNew|Import project'), new_project_path(anchor: 'import_project') -%h1.page-title.gl-font-size-h-display.gl-flex.gl-items-center - .gl-flex.gl-items-center.gl-justify-content-center +%h1.page-title.gl-text-size-h-display.gl-flex.gl-items-center + .gl-flex.gl-items-center.gl-justify-center = sprite_icon('tanuki', css_class: 'gl-mr-3', size: 48) = _('Import an exported GitLab project') %hr diff --git a/app/views/import/manifest/new.html.haml b/app/views/import/manifest/new.html.haml index 3d33e229f8f..25f87236260 100644 --- a/app/views/import/manifest/new.html.haml +++ b/app/views/import/manifest/new.html.haml @@ -3,7 +3,7 @@ - add_to_breadcrumbs s_('ProjectsNew|Import project'), new_project_path(anchor: 'import_project') -%h1.page-title.gl-font-size-h-display +%h1.page-title.gl-text-size-h-display = _('Manifest file import') = render 'import/shared/errors' diff --git a/app/views/import/manifest/status.html.haml b/app/views/import/manifest/status.html.haml index ced507de271..8a3e38e295e 100644 --- a/app/views/import/manifest/status.html.haml +++ b/app/views/import/manifest/status.html.haml @@ -1,6 +1,6 @@ - page_title _("Manifest import") -%h1.page-title.gl-font-size-h-display +%h1.page-title.gl-text-size-h-display = _('Manifest file import') = render 'import/githubish_status', provider: 'manifest' diff --git a/app/views/import/shared/_imported_badge.html.haml b/app/views/import/shared/_imported_badge.html.haml index a86d53668cd..9808bfcc92d 100644 --- a/app/views/import/shared/_imported_badge.html.haml +++ b/app/views/import/shared/_imported_badge.html.haml @@ -2,6 +2,6 @@ - text_only = local_assigns.fetch(:text_only, false) - if text_only - %span.has-tooltip.gl-leading-normal.gl-font-sm{ title: tooltip_title }= _('Imported') + %span.has-tooltip.gl-leading-normal.gl-text-sm{ title: tooltip_title }= _('Imported') - else = render Pajamas::BadgeComponent.new(_('Imported'), title: tooltip_title, class: 'has-tooltip') diff --git a/app/views/import/shared/_new_project_form.html.haml b/app/views/import/shared/_new_project_form.html.haml index 042d94ad1b6..4713632f6f0 100644 --- a/app/views/import/shared/_new_project_form.html.haml +++ b/app/views/import/shared/_new_project_form.html.haml @@ -18,7 +18,7 @@ .input-group-text.border-0 #{user_url(current_user.username)}/ = hidden_field_tag :namespace_id, current_user.namespace_id - .gl-align-self-center.gl-pl-5 / + .gl-self-center.gl-pl-5 / .form-group.col-12.col-sm-6.project-path = label_tag :path, _('Project slug'), class: 'label-bold' = text_field_tag :path, @path, placeholder: "my-awesome-project", class: "js-path-name form-control gl-form-input", required: true, aria: { required: true } diff --git a/app/views/invites/decline.html.haml b/app/views/invites/decline.html.haml index 64fd31cbd5a..b5ac6434322 100644 --- a/app/views/invites/decline.html.haml +++ b/app/views/invites/decline.html.haml @@ -1,8 +1,8 @@ - page_title _('Invitation declined') -.col-md-7.gl-display-flex.gl-flex-direction-column.gl-mx-auto.gl-w-full.gl-sm-w-auto - .gl-align-self-center.gl-mb-4.gl-mt-7.gl-sm-mt-0= sprite_icon('check-circle', size: 48, css_class: 'gl-text-green-400') - %h2.gl-font-size-h2= _('You successfully declined the invitation') +.col-md-7.gl-flex.gl-flex-col.gl-mx-auto.gl-w-full.sm:gl-w-auto + .gl-self-center.gl-mb-4.gl-mt-7.sm:gl-mt-0= sprite_icon('check-circle', size: 48, css_class: 'gl-text-green-400') + %h2.gl-text-size-h2= _('You successfully declined the invitation') %p = html_escape(_('We will notify %{inviter} that you declined their invitation to join GitLab. You will stop receiving reminders.')) % { inviter: sanitize_name(@member.created_by.name) } %p diff --git a/app/views/invites/show.html.haml b/app/views/invites/show.html.haml index d368f013e6b..17199d652f5 100644 --- a/app/views/invites/show.html.haml +++ b/app/views/invites/show.html.haml @@ -1,5 +1,5 @@ - page_title _("Invitation") -%h1.page-title.gl-font-size-h-display= _("Invitation") +%h1.page-title.gl-text-size-h-display= _("Invitation") - if current_user_matches_invite? - if member? diff --git a/app/views/layouts/devise.html.haml b/app/views/layouts/devise.html.haml index d01c438aa3c..11a1b762973 100644 --- a/app/views/layouts/devise.html.haml +++ b/app/views/layouts/devise.html.haml @@ -8,15 +8,15 @@ = header_message = render "layouts/init_client_detection_flags" = yield :sessions_broadcast - .gl-h-full.gl-display-flex.gl-flex-wrap - .container.gl-align-self-center + .gl-h-full.gl-flex.gl-flex-wrap + .container.gl-self-center .content = render "layouts/flash" - if custom_text.present? .row.gl-mt-5.gl-gap-y-5 .col-md.order-12.sm-bg-gray .col-sm-12 - %h1.gl-mb-5.gl-font-size-h2 + %h1.gl-mb-5.gl-text-size-h2 = brand_title #js-custom-sign-in-description= custom_text .col-md.order-md-12 @@ -28,9 +28,9 @@ .gl-my-5 .col-sm-12.gl-text-center = brand_image - %h1.mb-3.gl-font-size-h2 + %h1.mb-3.gl-text-size-h2 = brand_title - .gl-w-full.gl-sm-w-half.gl-ml-auto.gl-mr-auto.bar + .gl-w-full.gl-ml-auto.gl-mr-auto.bar{ class: 'sm:gl-w-1/2' } = yield = render 'devise/shared/footer' diff --git a/app/views/layouts/devise_empty.html.haml b/app/views/layouts/devise_empty.html.haml index 93ed36918e0..74d1a1b4ecf 100644 --- a/app/views/layouts/devise_empty.html.haml +++ b/app/views/layouts/devise_empty.html.haml @@ -9,8 +9,8 @@ = header_message = render "layouts/init_client_detection_flags" = render "layouts/header/empty" - .gl-h-full.gl-display-flex.gl-flex-wrap - .container.gl-align-self-center + .gl-h-full.gl-flex.gl-flex-wrap + .container.gl-self-center .content = render "layouts/flash" = yield diff --git a/app/views/layouts/fullscreen.html.haml b/app/views/layouts/fullscreen.html.haml index 2271411069f..1ad34355e76 100644 --- a/app/views/layouts/fullscreen.html.haml +++ b/app/views/layouts/fullscreen.html.haml @@ -5,7 +5,7 @@ = render 'peek/bar' = header_message .gl--flex-full.gl-h-full - .gl--flex-full.gl-flex-direction-column.gl-w-full + .gl--flex-full.gl-flex-col.gl-w-full .alert-wrapper = render 'shared/outdated_browser' = render "layouts/broadcast" diff --git a/app/views/layouts/header/_super_sidebar_logged_out.haml b/app/views/layouts/header/_super_sidebar_logged_out.haml index 8f872ecac10..7c5955db45f 100644 --- a/app/views/layouts/header/_super_sidebar_logged_out.haml +++ b/app/views/layouts/header/_super_sidebar_logged_out.haml @@ -1,8 +1,8 @@ %header.header-logged-out{ data: { testid: 'navbar' } } %a.gl-sr-only.gl-accessibility{ href: "#content-body" } Skip to content .container-fluid - %nav.header-logged-out-nav.gl-display-flex.gl-gap-3.gl-justify-content-space-between{ 'aria-label': s_('LoggedOutMarketingHeader|Explore GitLab') } - .gl-display-flex.gl-align-items-center.gl-gap-1 + %nav.header-logged-out-nav.gl-flex.gl-gap-3.gl-justify-between{ 'aria-label': s_('LoggedOutMarketingHeader|Explore GitLab') } + .gl-flex.gl-items-center.gl-gap-1 %span.gl-sr-only GitLab = link_to root_path, title: _('Homepage'), id: 'logo', class: 'header-logged-out-logo has-tooltip', aria: { label: _('Homepage') }, **tracking_attrs('main_navigation', 'click_gitlab_logo_link', 'navigation_top') do = brand_header_logo @@ -10,7 +10,7 @@ = gl_badge_tag({ variant: :success }, { href: Gitlab::Saas.canary_toggle_com_url, data: { testid: 'canary_badge_link' }, target: :_blank, rel: 'noopener noreferrer', class: 'canary-badge' }) do = s_('GitLab Next|Next') - %ul.gl-list-none.gl-p-0.gl-m-0.gl-display-flex.gl-gap-3.gl-align-items-center.gl-flex-grow-1 + %ul.gl-list-none.gl-p-0.gl-m-0.gl-flex.gl-gap-3.gl-items-center.gl-grow - if Gitlab.com? %li.header-logged-out-nav-item.header-logged-out-dropdown.md:gl-hidden %button.header-logged-out-toggle{ type: "button", data: { toggle: "dropdown" } } @@ -43,7 +43,7 @@ = link_to _("Explore"), explore_root_path, class: '' - if header_link?(:sign_in) - %ul.gl-list-none.gl-p-0.gl-m-0.gl-display-flex.gl-gap-3.gl-align-items-center.gl-justify-content-end + %ul.gl-list-none.gl-p-0.gl-m-0.gl-flex.gl-gap-3.gl-items-center.gl-justify-end %li.header-logged-out-nav-item = link_to _('Sign in'), new_session_path(:user, redirect_to_referer: 'yes') - if allow_signup? diff --git a/app/views/layouts/minimal.html.haml b/app/views/layouts/minimal.html.haml index 6150addadb6..805bf3b1196 100644 --- a/app/views/layouts/minimal.html.haml +++ b/app/views/layouts/minimal.html.haml @@ -10,8 +10,8 @@ = render 'peek/bar' = render 'layouts/published_experiments' = render "layouts/header/empty" - .layout-page.gl-h-full.borderless.gl-display-flex.gl-flex-wrap - .content-wrapper.gl-pt-6{ class: 'gl-md-pt-11!' } + .layout-page.gl-h-full.borderless.gl-flex.gl-flex-wrap + .content-wrapper.gl-pt-6{ class: 'md:!gl-pt-11' } %div{ class: container_class } %main#content-body.content = render "layouts/flash" unless @hide_flash diff --git a/app/views/layouts/nav/_top_bar.html.haml b/app/views/layouts/nav/_top_bar.html.haml index 02e58637678..e74ed4da243 100644 --- a/app/views/layouts/nav/_top_bar.html.haml +++ b/app/views/layouts/nav/_top_bar.html.haml @@ -1,5 +1,5 @@ %div{ class: 'top-bar-fixed container-fluid', data: { testid: 'top-bar' } } - .top-bar-container.gl-display-flex.gl-align-items-center.gl-gap-2 + .top-bar-container.gl-flex.gl-items-center.gl-gap-2 = render Pajamas::ButtonComponent.new(icon: 'sidebar', category: :tertiary, button_options: { class: 'js-super-sidebar-toggle-expand super-sidebar-toggle -gl-ml-3', aria: { controls: 'super-sidebar', expanded: 'false', label: _('Primary navigation sidebar') } }) = render "layouts/nav/breadcrumbs/breadcrumbs" = render "layouts/nav/work_items/feedback_badge" diff --git a/app/views/organizations/organizations/activity.html.haml b/app/views/organizations/organizations/activity.html.haml index ba604e54365..8bcb1b37b38 100644 --- a/app/views/organizations/organizations/activity.html.haml +++ b/app/views/organizations/organizations/activity.html.haml @@ -1,5 +1,5 @@ - page_title _("Activity") -%h1.page-title.gl-font-size-h-display +%h1.page-title.gl-text-size-h-display = _("Activity") #js-organizations-activity{ data: { app_data: organization_activity_app_data(@organization) } } diff --git a/app/views/profiles/accounts/_providers.html.haml b/app/views/profiles/accounts/_providers.html.haml index 83d1f175284..85dc1474ef5 100644 --- a/app/views/profiles/accounts/_providers.html.haml +++ b/app/views/profiles/accounts/_providers.html.haml @@ -2,7 +2,7 @@ %label.label-bold.gl-mb-0 = s_('Profiles|Connected Accounts') %p.gl-text-secondary= s_('Profiles|Select a service to sign in with.') - .gl-display-flex.gl-flex-wrap.gl-gap-3 + .gl-flex.gl-flex-wrap.gl-gap-3 - providers.each do |provider| - unlink_allowed = unlink_provider_allowed?(provider) - link_allowed = link_provider_allowed?(provider) diff --git a/app/views/profiles/chat_names/index.html.haml b/app/views/profiles/chat_names/index.html.haml index 99284abb73d..31c1d6b0c08 100644 --- a/app/views/profiles/chat_names/index.html.haml +++ b/app/views/profiles/chat_names/index.html.haml @@ -8,7 +8,7 @@ %h4.gl-my-0 = page_title - %h5.gl-font-lg.gl-mt-0 + %h5.gl-text-lg.gl-mt-0 = sprintf(_('Active chat names (%{count})'), { count: @chat_names.size }) - if @chat_names.present? diff --git a/app/views/profiles/chat_names/new.html.haml b/app/views/profiles/chat_names/new.html.haml index 80e2dbb36e7..aea06e12a34 100644 --- a/app/views/profiles/chat_names/new.html.haml +++ b/app/views/profiles/chat_names/new.html.haml @@ -17,7 +17,7 @@ %p.gl-mb-0 = s_("SlackIntegration|You don't have to reauthorize this application if the permission scope changes in future releases.") - c.with_footer do - .gl-display-flex + .gl-flex = form_tag profile_chat_names_path, method: :post do = hidden_field_tag :token, @chat_name_token.token = render Pajamas::ButtonComponent.new(type: :submit, variant: :danger, button_options: { data: { testid: 'authorize-button' } }) do diff --git a/app/views/profiles/emails/index.html.haml b/app/views/profiles/emails/index.html.haml index abbc1fa55c5..36a801e54ef 100644 --- a/app/views/profiles/emails/index.html.haml +++ b/app/views/profiles/emails/index.html.haml @@ -1,6 +1,6 @@ - page_title _('Emails') -- profile_message = _('Used for avatar detection. You can change it in your %{openingTag}profile settings%{closingTag}.') % { openingTag: "".html_safe, closingTag: ''.html_safe} -- notification_message = _('Used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set.') % { openingTag: "".html_safe, closingTag: ''.html_safe} +- profile_message = _('Used for avatar detection. You can change it in your %{openingTag}profile settings%{closingTag}.') % { openingTag: "".html_safe, closingTag: ''.html_safe} +- notification_message = _('Used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set.') % { openingTag: "".html_safe, closingTag: ''.html_safe} - public_email_message = _('Your public email will be displayed on your public profile.') - commit_email_message = _('Used for web based operations, such as edits and merges.') - @force_desktop_expanded_sidebar = true @@ -47,7 +47,7 @@ = s_('Profiles|Default notification email') .gl-text-subtle.gl-text-sm= notification_message.html_safe - @emails.reject(&:user_primary_email?).each do |email| - %li{ class: 'gl-px-5!', data: { testid: 'email-row-content' } } + %li{ class: '!gl-px-5', data: { testid: 'email-row-content' } } .gl-flex.gl-justify-between.gl-flex-wrap.gl-gap-3 - unless email.confirmed? = render Pajamas::AlertComponent.new(dismissible: false, variant: :warning, alert_options: { class: 'gl-w-full' }) do |c| diff --git a/app/views/protected_branches/shared/_protected_branch.html.haml b/app/views/protected_branches/shared/_protected_branch.html.haml index 1b4fc11036d..bfd11457419 100644 --- a/app/views/protected_branches/shared/_protected_branch.html.haml +++ b/app/views/protected_branches/shared/_protected_branch.html.haml @@ -29,7 +29,7 @@ - else .gl-relative - if local_assigns[:protected_from_deletion] - %span.gl-absolute.gl-display-inline-block.gl-w-full.gl-h-full{ data: { container: 'body', toggle: 'popover', placement: local_assigns[:placemet], html: 'true', triggers: 'hover', content: local_assigns[:popover_content] } } + %span.gl-absolute.gl-inline-block.gl-w-full.gl-h-full{ data: { container: 'body', toggle: 'popover', placement: local_assigns[:placemet], html: 'true', triggers: 'hover', content: local_assigns[:popover_content] } } = render Pajamas::ButtonComponent.new(size: :small, variant: :danger, href: [protected_branch_entity, protected_branch, { update_section: 'js-protected-branches-settings' }], diff --git a/app/views/search/_results.html.haml b/app/views/search/_results.html.haml index b26cd9e30c4..45cdf73c757 100644 --- a/app/views/search/_results.html.haml +++ b/app/views/search/_results.html.haml @@ -1,3 +1,3 @@ -.gl-w-full.gl-flex-grow-1 +.gl-w-full.gl-grow = render partial: 'search/results_status' = render partial: 'search/results_list' diff --git a/app/views/search/_results_status.html.haml b/app/views/search/_results_status.html.haml index 9108f4cd660..83c45b1168d 100644 --- a/app/views/search/_results_status.html.haml +++ b/app/views/search/_results_status.html.haml @@ -1,4 +1,4 @@ -.search-results-status.sm:gl-flex.gl-items-start.gl-justify-content-space-between.gl-my-4{ class: ('lg:gl-hidden' if @search_objects.to_a.empty?) } +.search-results-status.sm:gl-flex.gl-items-start.gl-justify-between.gl-my-4{ class: ('lg:gl-hidden' if @search_objects.to_a.empty?) } - unless @search_objects.to_a.empty? %div - unless @search_service_presenter.without_count? @@ -8,7 +8,7 @@ - link_to_project = link_to(@project.full_name, @project, class: 'search-wrap-f-md-down') - if @scope == 'blobs' %span= _("in") - .gl-display-inline-block + .gl-inline-block #js-blob-ref-switcher{ data: { "project-id" => @project.id, "ref" => repository_ref(@project), "field-name": "repository_ref" } } %span= safe_format(s_('SearchCodeResults|of %{link_to_project}'), link_to_project: link_to_project) - else @@ -16,8 +16,8 @@ - elsif @group - link_to_group = link_to(@group.name, @group, class: 'ml-md-1') = safe_format(_("in group %{link_to_group}"), link_to_group: link_to_group) - .gl-flex.gl-gap-3.gl-mt-3.gl-sm-mt-0 - = render Pajamas::ButtonComponent.new(category: 'primary', icon: 'filter', button_options: {id: 'js-open-mobile-filters', class: 'lg:gl-hidden gl-flex-grow-1 gl-md-flex-grow-0'}) do + .gl-flex.gl-gap-3.gl-mt-3.sm:gl-mt-0 + = render Pajamas::ButtonComponent.new(category: 'primary', icon: 'filter', button_options: {id: 'js-open-mobile-filters', class: 'lg:gl-hidden gl-grow md:gl-grow-0'}) do = s_('GlobalSearch|Filters') - if @search_service_presenter.show_sort_dropdown? && !@search_objects.to_a.empty? - #js-search-sort{ data: { "search-sort-options" => search_sort_options.to_json }, class: "gl-flex-grow-1 gl-md-flex-grow-0" } + #js-search-sort{ data: { "search-sort-options" => search_sort_options.to_json }, class: "gl-grow md:gl-grow-0" } diff --git a/app/views/search/results/_blob_data.html.haml b/app/views/search/results/_blob_data.html.haml index ab3b37539a0..1ede42cfe11 100644 --- a/app/views/search/results/_blob_data.html.haml +++ b/app/views/search/results/_blob_data.html.haml @@ -13,6 +13,6 @@ - else .file-content.code .nothing-here-block - .gl-text-gray-600.gl-font-sm + .gl-text-gray-600.gl-text-sm - max_file_size_indexed = Gitlab::CurrentSettings.elasticsearch_indexed_file_size_limit_kb.kilobytes = _('The file could not be displayed because it is empty or larger than the maximum file size indexed (%{size}).') % { size: number_to_human_size(max_file_size_indexed) } diff --git a/app/views/search/results/_blob_highlight.html.haml b/app/views/search/results/_blob_highlight.html.haml index a334cf771a9..5c40d2b5dee 100644 --- a/app/views/search/results/_blob_highlight.html.haml +++ b/app/views/search/results/_blob_highlight.html.haml @@ -7,9 +7,9 @@ - blob_highlight = blob.present.highlight_and_trim(trim_length: 1024, ellipsis_svg: sprite_icon('ellipsis_h', size: 12, css_class: "gl-text-gray-700")) - blob_highlight.lines.each_with_index do |line, index| - i = index + offset - .line_holder.code-search-line.gl-display-flex + .line_holder.code-search-line.gl-flex .line-numbers - .gl-display-flex + .gl-flex %span.diff-line-num.gl-pl-3 %a.has-tooltip{ href: "#{blame_link}#L#{i}", id: "blame-L#{i}", @@ -20,7 +20,7 @@ title: _('View blame') } = sprite_icon('git') %span.diff-line-num.flex-grow-1.gl-pr-3 - %a{ href: "#{blob_link}#L#{i}", id: "blob-L#{i}", 'data-line-number' => i, class: 'gl-display-flex! gl-align-items-center gl-justify-content-end' } + %a{ href: "#{blob_link}#L#{i}", id: "blob-L#{i}", 'data-line-number' => i, class: '!gl-flex gl-items-center gl-justify-end' } = i %pre.code.highlight.flex-grow-1 %code diff --git a/app/views/search/results/_issuable.html.haml b/app/views/search/results/_issuable.html.haml index 908802866e8..2d8342144b2 100644 --- a/app/views/search/results/_issuable.html.haml +++ b/app/views/search/results/_issuable.html.haml @@ -1,33 +1,33 @@ - position = local_assigns.fetch(:position, nil) -.search-result-row.row.gl-display-flex.gl-sm-flex-direction-row.gl-flex-direction-column.gl-mt-5{ class: 'gl-pb-5! gl-mb-0!' } +.search-result-row.row.gl-flex.sm:gl-flex-row.gl-flex-col.gl-mt-5{ class: '!gl-pb-5 !gl-mb-0' } .col-sm-9 - %span.gl-display-flex.gl-align-items-center + %span.gl-flex.gl-items-center = gl_badge_tag issuable_state_text(issuable), variant: issuable_state_to_badge_class(issuable) = sprite_icon('eye-slash', css_class: 'gl-text-secondary gl-ml-2') if issuable.respond_to?(:confidential?) && issuable.confidential? = link_to issuable_path(issuable), data: { event_tracking: 'click_search_result', event_label: @scope, event_value: position, event_property: @search_term }, class: 'gl-w-full' do %span.term.str-truncated.gl-font-bold.gl-ml-2= simple_search_highlight_and_truncate(issuable.title, @search_term) - .gl-text-secondary.gl-mb-3.gl-mt-2.gl-font-sm + .gl-text-secondary.gl-mb-3.gl-mt-2.gl-text-sm = issuable_project_reference(issuable) · = sprintf(s_('created %{issuable_created} by %{author}'), { issuable_created: time_ago_with_tooltip(issuable.created_at, placement: 'bottom'), author: link_to_member(issuable.author, avatar: false) }).html_safe - if (target_branch = issuable_visible_target_branch(issuable)) - %span.project-ref-path.has-tooltip.gl-inline-block.gl-text-truncate.gl-max-w-26.gl-align-bottom{ title: _('Target branch: %{target_branch}') % {target_branch: target_branch} } + %span.project-ref-path.has-tooltip.gl-inline-block.gl-truncate.gl-max-w-26.gl-align-bottom{ title: _('Target branch: %{target_branch}') % {target_branch: target_branch} }   - = link_to project_ref_path(issuable.project, target_branch), class: 'ref-name gl-text-secondary!' do + = link_to project_ref_path(issuable.project, target_branch), class: 'ref-name !gl-text-secondary' do = sprite_icon('branch', size: 12, css_class: 'fork-sprite') = target_branch - .description.term.gl-px-0.gl-font-sm + .description.term.gl-px-0.gl-text-sm = highlight_and_truncate_issuable(issuable, @search_term, @search_highlight) - if issuable.labels.any? .gl-mt-3 - presented_labels_sorted_by_title(issuable.labels, issuable.project).each do |label| = link_to_label(label) - .col-sm-3.gl-mt-3.gl-sm-mt-0.gl-text-right + .col-sm-3.gl-mt-3.sm:gl-mt-0.gl-text-right - if issuable.respond_to?(:upvotes_count) && issuable.upvotes_count > 0 %li.gl-list-none %span.has-tooltip{ title: _('Upvotes') } = sprite_icon('thumb-up', css_class: "gl-align-middle") = issuable.upvotes_count - %span.gl-text-secondary.gl-font-sm= sprintf(s_('updated %{time_ago}'), { time_ago: time_ago_with_tooltip(issuable.updated_at, placement: 'bottom') }).html_safe + %span.gl-text-secondary.gl-text-sm= sprintf(s_('updated %{time_ago}'), { time_ago: time_ago_with_tooltip(issuable.updated_at, placement: 'bottom') }).html_safe diff --git a/app/views/search/results/_milestone.html.haml b/app/views/search/results/_milestone.html.haml index 2a13668ede3..fb338c4fbf1 100644 --- a/app/views/search/results/_milestone.html.haml +++ b/app/views/search/results/_milestone.html.haml @@ -3,7 +3,7 @@ - position = index + 1 .search-result-row - = link_to project_milestone_path(milestone.project, milestone), class: 'gl-font-bold gl-text-black-normal', data: { event_tracking: 'click_search_result', event_label: @scope, event_value: position, event_property: @search_term } do + = link_to project_milestone_path(milestone.project, milestone), class: 'gl-font-bold gl-text-default', data: { event_tracking: 'click_search_result', event_label: @scope, event_value: position, event_property: @search_term } do %span.term.str-truncated= simple_search_highlight_and_truncate(milestone.title, @search_term) - if milestone.project_milestone? diff --git a/app/views/search/results/_note.html.haml b/app/views/search/results/_note.html.haml index a73dffdab0d..1354d43a4ce 100644 --- a/app/views/search/results/_note.html.haml +++ b/app/views/search/results/_note.html.haml @@ -7,9 +7,9 @@ .search-result-row .note-search-caption.gl-max-w-full - .gl-font-sm.gl-text-secondary.gl-float-right= time_ago_with_tooltip(note.created_at, placement: 'bottom', html_class: 'note-created-ago') - .gl-display-inline-block.gl-text-truncate.search-max-w-inherit.gl-align-bottom - .gl-font-bold= link_to_member(note.author, avatar: true, extra_class: 'gl-text-black-normal') + .gl-text-sm.gl-text-secondary.gl-float-right= time_ago_with_tooltip(note.created_at, placement: 'bottom', html_class: 'note-created-ago') + .gl-inline-block.gl-truncate.search-max-w-inherit.gl-align-bottom + .gl-font-bold= link_to_member(note.author, avatar: true, extra_class: 'gl-text-default') .gl-text-secondary = _("Commented on %{link_to_project}").html_safe % { link_to_project: link_to(project.full_name, project) } · diff --git a/app/views/search/results/_user.html.haml b/app/views/search/results/_user.html.haml index 262effafc5d..0b2df28d0f3 100644 --- a/app/views/search/results/_user.html.haml +++ b/app/views/search/results/_user.html.haml @@ -6,11 +6,11 @@ %div %div{ class: '!gl-inline-flex' } = render Pajamas::AvatarComponent.new(user, size: 32, alt: '') - .gl-ml-3{ class: 'gl-text-left!' } - = link_to user_path(user), class: 'gl-text-body', data: { event_tracking: 'click_search_result', event_label: @scope, event_value: position, event_property: @search_term } do - .gl-display-inline-block.gl-font-bold= simple_search_highlight_and_truncate(user.name, @search_term) + .gl-ml-3{ class: '!gl-text-left' } + = link_to user_path(user), class: 'gl-text-primary', data: { event_tracking: 'click_search_result', event_label: @scope, event_value: position, event_property: @search_term } do + .gl-inline-block.gl-font-bold= simple_search_highlight_and_truncate(user.name, @search_term) = user_status(user) - %div{ class: 'gl-text-left!' }= simple_search_highlight_and_truncate(user.to_reference, @search_term) + %div{ class: '!gl-text-left' }= simple_search_highlight_and_truncate(user.to_reference, @search_term) %td.gl-text-right{ data: { label: _('Activity') } } %div %span.gl-font-bold= _('User created:') diff --git a/app/views/search/results/_wiki_blob.html.haml b/app/views/search/results/_wiki_blob.html.haml index 4558e44cfcf..6c84eb7dbc1 100644 --- a/app/views/search/results/_wiki_blob.html.haml +++ b/app/views/search/results/_wiki_blob.html.haml @@ -2,8 +2,8 @@ - wiki_blob = local_assigns.fetch(:result, nil) - position = index + 1 -%div{ class: 'search-result-row gl-pb-3! gl-mt-5 gl-mb-0!' } - %span.gl-display-flex.gl-align-items-center +%div{ class: 'search-result-row !gl-pb-3 gl-mt-5 !gl-mb-0' } + %span.gl-flex.gl-items-center = link_to wiki_blob_link(wiki_blob), data: { event_tracking: 'click_search_result', event_label: @scope, event_value: position, event_property: @search_term }, class: 'gl-w-full' do %span.term.str-truncated.gl-font-bold= ::Wiki.canonicalize_filename(wiki_blob.path) .description.term.col-sm-10.gl-px-0 diff --git a/app/views/sent_notifications/unsubscribe.html.haml b/app/views/sent_notifications/unsubscribe.html.haml index 3e2373446ca..2c76f428b44 100644 --- a/app/views/sent_notifications/unsubscribe.html.haml +++ b/app/views/sent_notifications/unsubscribe.html.haml @@ -6,7 +6,7 @@ - noteable_url = show_project_path ? url_for([@sent_notification.project, noteable]) : breadcrumb_title_link - page_title _('Unsubscribe'), noteable_text, noteable_type.pluralize, project_path -%h1.page-title.gl-font-size-h-display +%h1.page-title.gl-text-size-h-display = _("Unsubscribe from %{type}") % { type: noteable_type } %p diff --git a/app/views/snippets/_snippets_scope_menu.html.haml b/app/views/snippets/_snippets_scope_menu.html.haml index 35d21e45c47..4745b3b888f 100644 --- a/app/views/snippets/_snippets_scope_menu.html.haml +++ b/app/views/snippets/_snippets_scope_menu.html.haml @@ -2,7 +2,7 @@ - include_private = local_assigns.fetch(:include_private, false) - params[:scope] ||= [] -= gl_tabs_nav({ class: 'js-snippets-nav-tabs gl-border-b-0 gl-overflow-x-auto gl-flex-grow-1 gl-flex-nowrap' }) do += gl_tabs_nav({ class: 'js-snippets-nav-tabs gl-border-b-0 gl-overflow-x-auto gl-grow gl-flex-nowrap' }) do = gl_tab_link_to subject_snippets_path(subject), { item_active: params[:scope].empty? } do = _('All') = gl_tab_counter_badge(include_private ? counts[:total] : counts[:are_public_or_internal]) diff --git a/app/views/snippets/edit.html.haml b/app/views/snippets/edit.html.haml index ff4fec807cf..5c699200d4f 100644 --- a/app/views/snippets/edit.html.haml +++ b/app/views/snippets/edit.html.haml @@ -3,6 +3,6 @@ - content_for :prefetch_asset_tags do - webpack_preload_asset_tag('monaco') -%h1.page-title.gl-font-size-h-display +%h1.page-title.gl-text-size-h-display = _("Edit snippet") = render 'shared/snippets/form', url: gitlab_snippet_path(@snippet) diff --git a/app/views/time_tracking/timelogs/index.html.haml b/app/views/time_tracking/timelogs/index.html.haml index b0bfc749606..f78d5753be6 100644 --- a/app/views/time_tracking/timelogs/index.html.haml +++ b/app/views/time_tracking/timelogs/index.html.haml @@ -1,7 +1,7 @@ - @force_fluid_layout = true - page_title _('Time tracking report') -.page-title-holder.gl-display-flex.gl-flex-align-items-center - %h1.page-title.gl-font-size-h-display= _('Time tracking report') +.page-title-holder.gl-flex.gl-flex-align-items-center + %h1.page-title.gl-text-size-h-display= _('Time tracking report') #js-timelogs-app{ data: { limit_to_hours: Gitlab::CurrentSettings.time_tracking_limit_to_hours.to_s } } diff --git a/app/views/user_settings/gpg_keys/_key.html.haml b/app/views/user_settings/gpg_keys/_key.html.haml index ec4a47ee347..fe8260349bd 100644 --- a/app/views/user_settings/gpg_keys/_key.html.haml +++ b/app/views/user_settings/gpg_keys/_key.html.haml @@ -2,17 +2,17 @@ %td{ data: { label: s_('Profiles|Key') } } %div{ class: '!gl-flex !gl-pl-0' } = sprite_icon('key', css_class: "settings-list-icon gl-hidden sm:gl-inline gl-mr-2") - .gl-display-flex.gl-flex-direction-column.gl-text-truncate - %p.gl-text-truncate.gl-m-0 + .gl-flex.gl-flex-col.gl-truncate + %p.gl-truncate.gl-m-0 %code= key.fingerprint - if key.subkeys.present? .gl-mt-3{ class: '!gl-text-left' } - %span.gl-font-sm + %span.gl-text-sm = _('Subkeys:') %ul.subkeys-list - key.subkeys.each do |subkey| %li - %p.gl-text-truncate.gl-m-0 + %p.gl-truncate.gl-m-0 %code= subkey.fingerprint %td{ data: { label: _('Status') } } diff --git a/app/views/user_settings/passwords/new.html.haml b/app/views/user_settings/passwords/new.html.haml index f171dffff63..d0671ea36f4 100644 --- a/app/views/user_settings/passwords/new.html.haml +++ b/app/views/user_settings/passwords/new.html.haml @@ -1,13 +1,13 @@ - page_title _('Update password') -.gl-sm-w-half.gl-ml-auto.gl-mr-auto +.gl-ml-auto.gl-mr-auto{ class: 'sm:gl-w-1/2' } %h1.gl-heading-1= _('Update password for %{current_name}') % { current_name: current_user.name } %p.gl-text-secondary = _("To continue, please update your password. After you update, you'll be directed to sign in again.") .info-well .well-segment - .gl-display-flex.gl-align-items-center + .gl-flex.gl-items-center = render Pajamas::AvatarComponent.new(current_user, size: 24, avatar_options: { data: { qa_selector: 'user_avatar_content' }, title: current_user.username }) .gl-pl-4.gl-break-all %span= _('Signed in as %{username}') % { username: '@' + current_user.username } diff --git a/app/views/user_settings/profiles/show.html.haml b/app/views/user_settings/profiles/show.html.haml index e30c38ae76b..f4ae768cb40 100644 --- a/app/views/user_settings/profiles/show.html.haml +++ b/app/views/user_settings/profiles/show.html.haml @@ -31,7 +31,7 @@ = link_to avatar_icon_for_user(@user, 400), target: '_blank', rel: 'noopener noreferrer' do = render Pajamas::AvatarComponent.new(@user, size: 96, alt: "", class: 'gl-float-left gl-mr-5') %h5.gl-mt-0= s_("Profiles|Upload new avatar") - .gl-display-flex.gl-align-items-center.gl-my-3 + .gl-flex.gl-items-center.gl-my-3 = render Pajamas::ButtonComponent.new(button_options: { class: 'js-choose-user-avatar-button' }) do = s_("Profiles|Choose file...") %span.gl-ml-3.js-avatar-filename= s_("Profiles|No file chosen.") diff --git a/app/views/user_settings/ssh_keys/_key.html.haml b/app/views/user_settings/ssh_keys/_key.html.haml index 4584d34d076..3b4353ec2c0 100644 --- a/app/views/user_settings/ssh_keys/_key.html.haml +++ b/app/views/user_settings/ssh_keys/_key.html.haml @@ -6,13 +6,13 @@ = key.title %td{ data: { label: s_('Profiles|Key'), testid: 'key' } } - .gl-align-items-center{ class: 'gl-display-flex! gl-pl-0!' } + .gl-items-center{ class: '!gl-flex !gl-pl-0' } - if key.valid? && !key.expired? = sprite_icon('key', css_class: icon_classes) - else - %span.gl-display-inline-block.has-tooltip{ title: ssh_key_expiration_tooltip(key) } + %span.gl-inline-block.has-tooltip{ title: ssh_key_expiration_tooltip(key) } = sprite_icon('warning-solid', css_class: icon_classes) - %span.gl-text-truncate.gl-sm-ml-3 + %span.gl-truncate.sm:gl-ml-3 = key.fingerprint %td{ data: { label: s_('Profiles|Usage type'), testid: 'usage-type' } } diff --git a/app/views/users/_overview.html.haml b/app/views/users/_overview.html.haml index c1e98c4ff5f..658ccc127d8 100644 --- a/app/views/users/_overview.html.haml +++ b/app/views/users/_overview.html.haml @@ -2,7 +2,7 @@ .profile-readme-wrapper.gl-relative.gl-w-full.gl-pt-5 .profile-readme.read-more-container.gl-relative.justify-content-center.gl-border.gl-rounded-base.gl-overflow-hidden{ data: { 'read-more-height': 400 } } .read-more-content.gl-py-5.gl-px-6 - .gl-display-flex + .gl-flex = render Pajamas::BreadcrumbComponent.new(class: 'gl-mb-4') do |c| - c.with_item(text: @user.username, href: project_path(@user.user_project)) - c.with_item(text: @user.user_readme.path, href: @user.user_project.readme_url) @@ -11,16 +11,16 @@ .gl-ml-auto = link_to _('Edit file'), edit_blob_path(@user.user_project, @user.user_project.default_branch, @user.user_readme.path) = render 'projects/blob/viewer', viewer: @user.user_readme.rich_viewer, load_async: false - .js-read-more-trigger.read-more-trigger.gl-h-8.gl-absolute.gl-z-2.gl-bg-default.gl-border-t.gl-border-t-default.gl-px-6.gl-rounded-bottom-base.gl-cursor-pointer - = render Pajamas::ButtonComponent.new(variant: :link, button_text_classes: 'gl-display-flex gl-align-items-center gl-gap-1', button_options: { class: 'gl-mt-4 -gl-ml-1', 'aria-label': _("Expand Readme") }) do + .js-read-more-trigger.read-more-trigger.gl-h-8.gl-absolute.gl-z-2.gl-bg-default.gl-border-t.gl-border-t-default.gl-px-6.gl-rounded-b-base.gl-cursor-pointer + = render Pajamas::ButtonComponent.new(variant: :link, button_text_classes: 'gl-flex gl-items-center gl-gap-1', button_options: { class: 'gl-mt-4 -gl-ml-1', 'aria-label': _("Expand Readme") }) do = sprite_icon('chevron-down', size: 14) = _("Read more") - if can?(current_user, :read_cross_project) - .gl-align-self-start.gl-overflow-hidden + .gl-self-start.gl-overflow-hidden .activities-block - .gl-display-flex.gl-align-items-baseline - %h2.gl-heading-3.gl-flex-grow-1{ class: 'gl-mt-5! gl-mb-3!' } + .gl-flex.gl-items-baseline + %h2.gl-heading-3.gl-grow{ class: '!gl-mt-5 !gl-mb-3' } = s_('UserProfile|Activity') = link_to s_('UserProfile|View all'), user_activity_path, class: "hide js-view-all" @@ -37,8 +37,8 @@ - if @user.personal_projects.any? .projects-block.gl-w-full - .gl-display-flex.gl-align-items-baseline - %h2.gl-heading-3.gl-flex-grow-1{ class: 'gl-mt-5! gl-mb-3!' } + .gl-flex.gl-items-baseline + %h2.gl-heading-3.gl-grow{ class: '!gl-mt-5 !gl-mb-3' } = s_('UserProfile|Personal projects') = link_to s_('UserProfile|View all'), user_projects_path, class: "hide js-view-all" .overview-content-list{ data: { href: user_projects_path } } diff --git a/app/views/users/_profile_sidebar.html.haml b/app/views/users/_profile_sidebar.html.haml index 226edc1daab..2b2c64f7d8e 100644 --- a/app/views/users/_profile_sidebar.html.haml +++ b/app/views/users/_profile_sidebar.html.haml @@ -1,23 +1,23 @@ .user-profile-sidebar - .profile-header.gl-pb-5.gl-pt-3.gl-overflow-y-auto.gl-sm-pr-4 + .profile-header.gl-pb-5.gl-pt-3.gl-overflow-y-auto.sm:gl-pr-4 .gl-align-top.gl-text-left.gl-max-w-80.gl-wrap-anywhere .user-info - if @user.confirmed? - .gl-flex.gl-gap-4.gl-flex-direction-column + .gl-flex.gl-gap-4.gl-flex-col - if @user.pronouns.present? || @user.pronunciation.present? || @user.bio.present? %div - %h2.gl-font-base.gl-mb-2.gl-mt-4= s_('UserProfile|About') - .gl-flex.gl-gap-2.gl-flex-direction-column + %h2.gl-text-base.gl-mb-2.gl-mt-4= s_('UserProfile|About') + .gl-flex.gl-gap-2.gl-flex-col - if @user.pronouns.present? || @user.pronunciation.present? .gl-mb-2 - if @user.pronunciation.present? %p.gl-m-0 = s_("UserProfile|Pronounced as:") - %span.gl-font-sm.gl-text-secondary.gl-inline-flex= @user.pronunciation + %span.gl-text-sm.gl-text-secondary.gl-inline-flex= @user.pronunciation - if @user.pronouns.present? %p.gl-m-0 = s_("UserProfile|Pronouns:") - %span.gl-font-sm.gl-text-secondary.gl-inline-flex= @user.pronouns + %span.gl-text-sm.gl-text-secondary.gl-inline-flex= @user.pronouns - if @user.bio.present? %p.profile-user-bio.gl-mb-0 = @user.bio @@ -27,7 +27,7 @@ - user_local_time = local_time(@user.timezone) %div{ itemprop: 'address', itemscope: true, itemtype: 'https://schema.org/PostalAddress' } - %h2.gl-font-base.gl-mb-2.gl-mt-4= s_('UserProfile|Info') + %h2.gl-text-base.gl-mb-2.gl-mt-4= s_('UserProfile|Info') - if work_information(@user).present? .gl-flex.gl-gap-2.gl-mb-2 = sprite_icon('work', css_class: 'gl-fill-icon-subtle gl-mt-1 flex-shrink-0') @@ -49,7 +49,7 @@ - if has_contact_info?(@user) .gl-text-gray-900 - %h2.gl-font-base.gl-mb-2.gl-mt-4= s_('UserProfile|Contact') + %h2.gl-text-base.gl-mb-2.gl-mt-4= s_('UserProfile|Contact') - if @user.website_url.present? .gl-flex.gl-gap-2.gl-mb-2 = sprite_icon('earth', css_class: 'gl-fill-icon-subtle gl-mt-1 flex-shrink-0') diff --git a/app/views/users/_view_gpg_keys.html.haml b/app/views/users/_view_gpg_keys.html.haml index aa0f69ffe3c..e42f66eb8c2 100644 --- a/app/views/users/_view_gpg_keys.html.haml +++ b/app/views/users/_view_gpg_keys.html.haml @@ -2,4 +2,4 @@ - if verified_gpg_keys.any? = render Pajamas::ButtonComponent.new(href: user_gpg_keys_path, icon: 'key', - button_options: { class: 'gl-flex-grow-1 gl-mx-1 has-tooltip', title: n_('View public GPG key', 'View public GPG keys', verified_gpg_keys.length), data: { toggle: 'tooltip', placement: 'bottom', container: 'body' }}) + button_options: { class: 'gl-grow gl-mx-1 has-tooltip', title: n_('View public GPG key', 'View public GPG keys', verified_gpg_keys.length), data: { toggle: 'tooltip', placement: 'bottom', container: 'body' }}) diff --git a/app/views/users/calendar_activities.html.haml b/app/views/users/calendar_activities.html.haml index 137e63290d5..43c940942da 100644 --- a/app/views/users/calendar_activities.html.haml +++ b/app/views/users/calendar_activities.html.haml @@ -6,7 +6,7 @@ - @events.sort_by(&:created_at).each do |event| %li %span.light.js-localtime{ :data => { :datetime => event.created_at.utc.strftime('%Y-%m-%dT%H:%M:%SZ'), :toggle => 'tooltip', :placement => 'top' } } - = sprite_icon('clock', css_class: 'gl-vertical-align-text-bottom') + = sprite_icon('clock', css_class: 'gl-align-text-bottom') = event.created_at.to_time.in_time_zone(local_timezone_instance(@user.timezone)).strftime('%-I:%M%P') - if event.visible_to_user?(current_user) - if event.push_action? diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index 7d139d3b26a..dcc0ca6ec68 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -14,9 +14,9 @@ = auto_discovery_link_tag(:atom, user_url(@user, format: :atom), title: "#{@user.name} activity") %div{ class: container_class } - .user-profile-header.gl-display-flex.gl-justify-content-space-between.gl-flex-direction-column.gl-md-flex-direction-row-reverse.gl-my-5{ 'data-testid': 'user-profile-header' } + .user-profile-header.gl-flex.gl-justify-between.gl-flex-col.md:gl-flex-row-reverse.gl-my-5{ 'data-testid': 'user-profile-header' } %div - .cover-controls.gl-display-flex.gl-gap-3.gl-mb-4.gl-md-justify-content-end.gl-md-flex-direction-row-reverse + .cover-controls.gl-flex.gl-gap-3.gl-mb-4.md:gl-justify-end.md:gl-flex-row-reverse .js-user-profile-actions{ data: user_profile_actions_data(@user) } = render 'users/follow_user' -# The following edit button is mutually exclusive to the follow user button, they won't be shown together @@ -26,20 +26,20 @@ = s_("UserProfile|Edit profile") = render 'users/view_gpg_keys' = render 'users/view_user_in_admin_area' - .gl-display-flex.gl-flex-direction-row.gl-align-items-center.gl-gap-x-5.gl-mt-2.gl-sm-mt-0 + .gl-flex.gl-flex-row.gl-items-center.gl-gap-x-5.gl-mt-2.sm:gl-mt-0 .user-image.gl-relative.gl-md-py-3 = link_to avatar_icon_for_user(@user, 400, current_user: current_user), target: '_blank', rel: 'noopener noreferrer', title: s_('UserProfile|View large avatar') do = render Pajamas::AvatarComponent.new(@user, alt: s_('UserProfile|User profile picture'), size: 96, avatar_options: { itemprop: "image" }) - if @user.status&.busy? - = render Pajamas::BadgeComponent.new(s_('UserProfile|Busy'), variant: 'warning', class: 'gl-absolute gl-display-flex gl-justify-content-center gl-align-items-center gl-left-1/2 gl-bg-gray-50 gl-border gl-border-white -gl-translate-x-1/2 gl-top-full -gl-mt-3') + = render Pajamas::BadgeComponent.new(s_('UserProfile|Busy'), variant: 'warning', class: 'gl-absolute gl-flex gl-justify-center gl-items-center gl-left-1/2 gl-bg-gray-50 gl-border gl-border-white -gl-translate-x-1/2 gl-top-full -gl-mt-3') %div - %h1.gl-heading-1.gl-leading-1.gl-mr-2{ class: 'gl-my-0!', itemprop: 'name' } + %h1.gl-heading-1.gl-leading-1.gl-mr-2{ class: '!gl-my-0', itemprop: 'name' } = user_display_name(@user) - .gl-font-size-h2.gl-text-gray-500.gl-font-normal.gl-my-0 + .gl-text-size-h2.gl-text-gray-500.gl-font-normal.gl-my-0 = @user.to_reference - if !@user.blocked? && @user.confirmed? && @user.status&.customized? - .gl-my-2.cover-status.gl-font-sm.gl-pt-2.gl-display-flex.gl-flex-direction-column - .gl-inline-flex.gl-gap-3.gl-align-items-baseline + .gl-my-2.cover-status.gl-text-sm.gl-pt-2.gl-flex.gl-flex-col + .gl-inline-flex.gl-gap-3.gl-items-baseline = emoji_icon(@user.status.emoji) = markdown_field(@user.status, :message) .user-profile{ class: @user.blocked? ? '' : 'user-profile-with-sidebar' } diff --git a/app/views/users/unsubscribes/show.html.haml b/app/views/users/unsubscribes/show.html.haml index d06c98955c8..44556bbc127 100644 --- a/app/views/users/unsubscribes/show.html.haml +++ b/app/views/users/unsubscribes/show.html.haml @@ -1,5 +1,5 @@ - page_title _("Unsubscribe"), _("Admin Notifications") -%h1.page-title.gl-font-size-h-display Unsubscribe from Admin notifications +%h1.page-title.gl-text-size-h-display Unsubscribe from Admin notifications = form_tag unsubscribe_path(Base64.urlsafe_encode64(@email)) do %p diff --git a/config/feature_flags/development/web_ide_oauth.yml b/config/feature_flags/development/web_ide_oauth.yml index fc3132d01b4..78aef7831e2 100644 --- a/config/feature_flags/development/web_ide_oauth.yml +++ b/config/feature_flags/development/web_ide_oauth.yml @@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/433324 milestone: '16.7' type: development group: group::ide -default_enabled: false +default_enabled: true diff --git a/config/feature_flags/gitlab_com_derisk/store_detumbled_email.yml b/config/feature_flags/gitlab_com_derisk/store_detumbled_email.yml new file mode 100644 index 00000000000..b25673dca93 --- /dev/null +++ b/config/feature_flags/gitlab_com_derisk/store_detumbled_email.yml @@ -0,0 +1,9 @@ +--- +name: store_detumbled_email +feature_issue_url: https://gitlab.com/gitlab-org/modelops/anti-abuse/team-tasks/-/work_items/827 +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/161663 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/478304 +milestone: '17.4' +group: group::anti-abuse +type: gitlab_com_derisk +default_enabled: false diff --git a/config/gitlab_loose_foreign_keys.yml b/config/gitlab_loose_foreign_keys.yml index 8bbd42d1f29..46306971965 100644 --- a/config/gitlab_loose_foreign_keys.yml +++ b/config/gitlab_loose_foreign_keys.yml @@ -412,6 +412,9 @@ security_scans: - table: p_ci_builds column: build_id on_delete: async_delete + - table: projects + column: project_id + on_delete: async_delete security_trainings: - table: projects column: project_id diff --git a/danger/cookie_setting/Dangerfile b/danger/cookie_setting/Dangerfile new file mode 100644 index 00000000000..c109f055886 --- /dev/null +++ b/danger/cookie_setting/Dangerfile @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +helper.all_changed_files.each do |filename| + next unless filename.end_with?('.rb') + next if filename.start_with?('spec/', 'ee/spec/', 'jh/spec/', 'qa/') + + cookie_setting.add_suggestions_for(filename) +end diff --git a/danger/plugins/cookie_setting.rb b/danger/plugins/cookie_setting.rb new file mode 100644 index 00000000000..f197ff2b375 --- /dev/null +++ b/danger/plugins/cookie_setting.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require_relative '../../tooling/danger/cookie_setting' + +module Danger + class CookieSetting < ::Danger::Plugin + def add_suggestions_for(filename) + Tooling::Danger::CookieSetting.new(filename, context: self).suggest + end + end +end diff --git a/db/docs/ci_job_variables.yml b/db/docs/ci_job_variables.yml index 1184664e758..3903e8f3077 100644 --- a/db/docs/ci_job_variables.yml +++ b/db/docs/ci_job_variables.yml @@ -9,3 +9,13 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/14784 milestone: '12.2' gitlab_schema: gitlab_ci sharding_key_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/463243 +desired_sharding_key: + project_id: + references: projects + backfill_via: + parent: + foreign_key: job_id + table: p_ci_builds + sharding_key: project_id + belongs_to: job + foreign_key_name: fk_rails_fbf3b34792_p diff --git a/db/docs/ci_pipelines.yml b/db/docs/ci_pipelines.yml index 6876237ba1d..dd5050f31f5 100644 --- a/db/docs/ci_pipelines.yml +++ b/db/docs/ci_pipelines.yml @@ -8,4 +8,5 @@ description: TODO introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/commit/c6ae290cea4b88ecaa9cfe0bc9d88e8fd32070c1 milestone: '9.0' gitlab_schema: gitlab_ci -sharding_key_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/458486 +sharding_key: + project_id: projects diff --git a/db/docs/p_ci_builds.yml b/db/docs/p_ci_builds.yml index 6630d343686..5aafb0473ba 100644 --- a/db/docs/p_ci_builds.yml +++ b/db/docs/p_ci_builds.yml @@ -12,4 +12,5 @@ description: Routing table for ci_builds introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/120873 milestone: '16.1' gitlab_schema: gitlab_ci -sharding_key_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/458488 +sharding_key: + project_id: projects diff --git a/db/docs/p_ci_job_annotations.yml b/db/docs/p_ci_job_annotations.yml index 571d0bcc063..ef71ffed3dd 100644 --- a/db/docs/p_ci_job_annotations.yml +++ b/db/docs/p_ci_job_annotations.yml @@ -10,3 +10,13 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/117319 milestone: '16.1' gitlab_schema: gitlab_ci sharding_key_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/463246 +desired_sharding_key: + project_id: + references: projects + backfill_via: + parent: + foreign_key: job_id + table: p_ci_builds + sharding_key: project_id + belongs_to: job + foreign_key_name: fk_rails_d4d0c0fa0f diff --git a/db/docs/p_ci_pipeline_variables.yml b/db/docs/p_ci_pipeline_variables.yml index 41409c1ebb1..7cd0139fe7d 100644 --- a/db/docs/p_ci_pipeline_variables.yml +++ b/db/docs/p_ci_pipeline_variables.yml @@ -9,3 +9,13 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/141270 milestone: '16.9' gitlab_schema: gitlab_ci sharding_key_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/463244 +desired_sharding_key: + project_id: + references: projects + backfill_via: + parent: + foreign_key: pipeline_id + table: ci_pipelines + sharding_key: project_id + belongs_to: pipeline + foreign_key_name: fk_f29c5f4380_p diff --git a/db/docs/security_scans.yml b/db/docs/security_scans.yml index ce73f46afe3..64d9177d56b 100644 --- a/db/docs/security_scans.yml +++ b/db/docs/security_scans.yml @@ -7,5 +7,5 @@ feature_categories: description: Stores information about the security scans that are a part of Ci::Build introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23669 milestone: '12.8' -gitlab_schema: gitlab_main +gitlab_schema: gitlab_sec sharding_key_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/454948 diff --git a/db/post_migrate/20240209153920_queue_purge_security_scans_with_empty_finding_data.rb b/db/post_migrate/20240209153920_queue_purge_security_scans_with_empty_finding_data.rb index 667354ef5ea..6c7404dd528 100644 --- a/db/post_migrate/20240209153920_queue_purge_security_scans_with_empty_finding_data.rb +++ b/db/post_migrate/20240209153920_queue_purge_security_scans_with_empty_finding_data.rb @@ -5,7 +5,7 @@ class QueuePurgeSecurityScansWithEmptyFindingData < Gitlab::Database::Migration[ disable_ddl_transaction! - restrict_gitlab_migration gitlab_schema: :gitlab_main + restrict_gitlab_migration gitlab_schema: :gitlab_sec MIGRATION = "PurgeSecurityScansWithEmptyFindingData" DELAY_INTERVAL = 2.minutes @@ -27,28 +27,36 @@ class QueuePurgeSecurityScansWithEmptyFindingData < Gitlab::Database::Migration[ end def up - return if Gitlab.com? || !Gitlab.ee? + # temporary until security_findings table is migrated + # https://gitlab.com/gitlab-org/gitlab/-/issues/477986' + Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas.with_suppressed do + break if Gitlab.com? || !Gitlab.ee? - first_succeeded_scan = SecurityScan.succeeded.first + first_succeeded_scan = SecurityScan.succeeded.first - return unless first_succeeded_scan + break unless first_succeeded_scan - first_finding = first_succeeded_scan.findings.first + first_finding = first_succeeded_scan.findings.first - return if first_finding&.finding_data.present? + break if first_finding&.finding_data.present? - queue_batched_background_migration( - MIGRATION, - :security_scans, - :id, - job_interval: DELAY_INTERVAL, - batch_size: BATCH_SIZE, - sub_batch_size: SUB_BATCH_SIZE, - batch_min_value: first_succeeded_scan.id - ) + queue_batched_background_migration( + MIGRATION, + :security_scans, + :id, + job_interval: DELAY_INTERVAL, + batch_size: BATCH_SIZE, + sub_batch_size: SUB_BATCH_SIZE, + batch_min_value: first_succeeded_scan.id + ) + end end def down - delete_batched_background_migration(MIGRATION, :security_scans, :id, []) + # temporary until security_findings table is migrated + # https://gitlab.com/gitlab-org/gitlab/-/issues/477986' + Gitlab::Database::QueryAnalyzers::RestrictAllowedSchemas.with_suppressed do + delete_batched_background_migration(MIGRATION, :security_scans, :id, []) + end end end diff --git a/db/post_migrate/20240320102510_finalize_purge_security_scans_with_empty_finding_data.rb b/db/post_migrate/20240320102510_finalize_purge_security_scans_with_empty_finding_data.rb index 2bc6caecf2c..468fba5ef8f 100644 --- a/db/post_migrate/20240320102510_finalize_purge_security_scans_with_empty_finding_data.rb +++ b/db/post_migrate/20240320102510_finalize_purge_security_scans_with_empty_finding_data.rb @@ -4,7 +4,7 @@ class FinalizePurgeSecurityScansWithEmptyFindingData < Gitlab::Database::Migrati disable_ddl_transaction! milestone '16.11' - restrict_gitlab_migration gitlab_schema: :gitlab_main + restrict_gitlab_migration gitlab_schema: :gitlab_sec def up return if Gitlab.com? || !Gitlab.ee? diff --git a/db/post_migrate/20240724123021_remove_projects_security_scans_project_id_fk.rb b/db/post_migrate/20240724123021_remove_projects_security_scans_project_id_fk.rb new file mode 100644 index 00000000000..e84386b4876 --- /dev/null +++ b/db/post_migrate/20240724123021_remove_projects_security_scans_project_id_fk.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +class RemoveProjectsSecurityScansProjectIdFk < Gitlab::Database::Migration[2.2] + milestone '17.3' + disable_ddl_transaction! + + FOREIGN_KEY_NAME = "fk_dbc89265b9" + + def up + with_lock_retries do + remove_foreign_key_if_exists(:security_scans, :projects, + name: FOREIGN_KEY_NAME, reverse_lock_order: true) + end + end + + def down + add_concurrent_foreign_key(:security_scans, :projects, + name: FOREIGN_KEY_NAME, column: :project_id, + target_column: :id, on_delete: :cascade) + end +end diff --git a/db/schema_migrations/20240724123021 b/db/schema_migrations/20240724123021 new file mode 100644 index 00000000000..3f66089c798 --- /dev/null +++ b/db/schema_migrations/20240724123021 @@ -0,0 +1 @@ +587b0beecb4c39ddf190303e6294b0e420562e89e480ef31b94c855aa4db1695 \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 96da61b7182..fb07ebe9739 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -33903,9 +33903,6 @@ ALTER TABLE ONLY web_hooks ALTER TABLE ONLY work_item_dates_sources ADD CONSTRAINT fk_dbbe8917ee FOREIGN KEY (due_date_sourcing_work_item_id) REFERENCES issues(id) ON DELETE SET NULL; -ALTER TABLE ONLY security_scans - ADD CONSTRAINT fk_dbc89265b9 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE; - ALTER TABLE ONLY boards_epic_board_positions ADD CONSTRAINT fk_dc62428d81 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE; diff --git a/doc/administration/operations/puma.md b/doc/administration/operations/puma.md index e448f48985e..0bc6604bb6c 100644 --- a/doc/administration/operations/puma.md +++ b/doc/administration/operations/puma.md @@ -211,8 +211,7 @@ configure this: echo some-password-here ``` - Note that in production, you should avoid storing the password on - disk and use a secure mechanism for retrieving a password, such as + Avoid storing the password on disk, and use a secure mechanism for retrieving a password, such as Vault. For example, the script might look like: ```shell diff --git a/doc/administration/reference_architectures/10k_users.md b/doc/administration/reference_architectures/10k_users.md index b8853814e7e..fc322e68fa4 100644 --- a/doc/administration/reference_architectures/10k_users.md +++ b/doc/administration/reference_architectures/10k_users.md @@ -50,7 +50,7 @@ specifically the [Before you start](index.md#before-you-start) and [Deciding whi 2. Can be optionally run on reputable third-party external PaaS Redis solutions. See [Provide your own Redis instances](#provide-your-own-redis-instances) and [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information. - Redis is primarily single threaded and doesn't significantly benefit from an increase in CPU cores. For this size of architecture it's strongly recommended having separate Cache and Persistent instances as specified to achieve optimum performance. 3. Recommended to be run with a reputable third-party load balancer or service (LB PaaS) which can provide HA capabilities. - Also note that sizing depends on selected Load Balancer as well as additional factors such as Network Bandwidth. Refer to [Load Balancers](index.md#load-balancers) for more information. + The sizing depends on selected Load Balancer and additional factors such as Network Bandwidth. Refer to [Load Balancers](index.md#load-balancers) for more information. 4. Should be run on reputable Cloud Provider or Self Managed solutions. See [Configure the object storage](#configure-the-object-storage) for more information. 5. Gitaly Cluster provides the benefits of fault tolerance, but comes with additional complexity of setup and management. Review the existing [technical limitations and considerations before deploying Gitaly Cluster](../gitaly/index.md#before-deploying-gitaly-cluster). If you want sharded Gitaly, use the same specs listed above for `Gitaly`. @@ -170,12 +170,12 @@ including CI and other workloads. If you have metrics to suggest that you have regularly higher throughput against the above endpoint targets, [large monorepos](index.md#large-monorepos) or notable [additional workloads](index.md#additional-workloads) these can notably impact the performance environment and [further adjustments may be required](index.md#scaling-an-environment). -If this applies to you, we strongly recommended referring to the linked documentation as well as 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 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. -Testing is done regularly via our [GitLab Performance Tool (GPT)](https://gitlab.com/gitlab-org/quality/performance) and its dataset, which is available for anyone to use. +Testing is done regularly by using the [GitLab Performance Tool (GPT)](https://gitlab.com/gitlab-org/quality/performance) and its dataset, which is available for anyone to use. The results of this testing are [available publicly on the GPT wiki](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest). For more information on our testing strategy [refer to this section of the documentation](index.md#validation-and-test-results). -The load balancers used for testing were HAProxy for Linux package environments or equivalent Cloud Provider services via NGINX Ingress for Cloud Native Hybrids. Note that these selections do not represent a specific requirement or recommendation as most [reputable load balancers are expected to work](#configure-the-external-load-balancer). +The load balancers used for testing were HAProxy for Linux package environments or equivalent Cloud Provider services with NGINX Ingress for Cloud Native Hybrids. These selections do not represent a specific requirement or recommendation as most [reputable load balancers are expected to work](#configure-the-external-load-balancer). ## Set up components @@ -521,7 +521,7 @@ A reputable provider or solution should be used for this. [Google Cloud SQL](htt If you use a third party external service: -1. Note that the HA Linux package PostgreSQL setup encompasses PostgreSQL, PgBouncer and Consul. These components would no longer be required when using a third party external service. +1. The HA Linux package PostgreSQL setup encompasses PostgreSQL, PgBouncer and Consul. These components would no longer be required when using a third party external service. 1. Set up PostgreSQL according to the [database requirements document](../../install/requirements.md#database). 1. Set up a `gitlab` username with a password of your choice. The `gitlab` user @@ -542,7 +542,7 @@ replication and failover requires: - An [internal load balancer](#configure-the-internal-load-balancer) (TCP) to balance requests between the PgBouncer nodes. - [Database Load Balancing](../postgresql/database_load_balancing.md) enabled. - A local PgBouncer service to be configured on each PostgreSQL node. Note that this is separate from the main PgBouncer cluster that tracks the primary. + A local PgBouncer service to be configured on each PostgreSQL node. This is separate from the main PgBouncer cluster that tracks the primary. The following IPs will be used as an example: @@ -2099,7 +2099,7 @@ the [HTTPS documentation](https://docs.gitlab.com/omnibus/settings/ssl/index.htm sudo gitlab-rake gitlab:db:configure ``` - Note that this requires the Rails node to be configured to connect to the primary database + This operation requires configuring the Rails node to connect to the primary database directly, [bypassing PgBouncer](../postgresql/pgbouncer.md#procedure-for-bypassing-pgbouncer). After migrations have completed, you must configure the node to pass through PgBouncer again. @@ -2299,7 +2299,7 @@ services where applicable): 2. Can be optionally run on reputable third-party external PaaS Redis solutions. See [Provide your own Redis instances](#provide-your-own-redis-instances) and [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information. - Redis is primarily single threaded and doesn't significantly benefit from an increase in CPU cores. For this size of architecture it's strongly recommended having separate Cache and Persistent instances as specified to achieve optimum performance. 3. Recommended to be run with a reputable third-party load balancer or service (LB PaaS) which can provide HA capabilities. - Also note that sizing depends on selected Load Balancer as well as additional factors such as Network Bandwidth. Refer to [Load Balancers](index.md#load-balancers) for more information. + Also, the sizing depends on selected Load Balancer and additional factors such as Network Bandwidth. Refer to [Load Balancers](index.md#load-balancers) for more information. 4. Should be run on reputable Cloud Provider or Self Managed solutions. See [Configure the object storage](#configure-the-object-storage) for more information. 5. Gitaly Cluster provides the benefits of fault tolerance, but comes with additional complexity of setup and management. Review the existing [technical limitations and considerations before deploying Gitaly Cluster](../gitaly/index.md#before-deploying-gitaly-cluster). If you want sharded Gitaly, use the same specs listed above for `Gitaly`. @@ -2402,7 +2402,7 @@ For further information on Webservice resource usage, see the Charts documentati It's also recommended deploying the NGINX controller pods across the Webservice nodes as a DaemonSet. This is to allow the controllers to scale dynamically with the Webservice pods they serve as well as take advantage of the higher network bandwidth larger machine types typically have. -Note that this isn't a strict requirement. The NGINX controller pods can be deployed as desired as long as they have enough resources to handle the web traffic. +This isn't a strict requirement. The NGINX controller pods can be deployed as desired as long as they have enough resources to handle the web traffic. #### Sidekiq diff --git a/doc/administration/reference_architectures/25k_users.md b/doc/administration/reference_architectures/25k_users.md index 5ebfe8730e0..4e25110c0ca 100644 --- a/doc/administration/reference_architectures/25k_users.md +++ b/doc/administration/reference_architectures/25k_users.md @@ -50,7 +50,7 @@ specifically the [Before you start](index.md#before-you-start) and [Deciding whi 2. Can be optionally run on reputable third-party external PaaS Redis solutions. See [Provide your own Redis instances](#provide-your-own-redis-instances) for more information. - Redis is primarily single threaded and doesn't significantly benefit from an increase in CPU cores. For this size of architecture it's strongly recommended having separate Cache and Persistent instances as specified to achieve optimum performance. 3. Recommended to be run with a reputable third-party load balancer or service (LB PaaS) which can provide HA capabilities. - Also note that sizing depends on selected Load Balancer as well as additional factors such as Network Bandwidth. Refer to [Load Balancers](index.md#load-balancers) for more information. + Also, the sizing depends on selected Load Balancer and additional factors such as Network Bandwidth. Refer to [Load Balancers](index.md#load-balancers) for more information. 4. Should be run on reputable Cloud Provider or Self Managed solutions. See [Configure the object storage](#configure-the-object-storage) for more information. 5. Gitaly Cluster provides the benefits of fault tolerance, but comes with additional complexity of setup and management. Review the existing [technical limitations and considerations before deploying Gitaly Cluster](../gitaly/index.md#before-deploying-gitaly-cluster). If you want sharded Gitaly, use the same specs listed above for `Gitaly`. @@ -170,12 +170,12 @@ including CI and other workloads. If you have metrics to suggest that you have regularly higher throughput against the above endpoint targets, [large monorepos](index.md#large-monorepos) or notable [additional workloads](index.md#additional-workloads) these can notably impact the performance environment and [further adjustments may be required](index.md#scaling-an-environment). -If this applies to you, we strongly recommended referring to the linked documentation as well as 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 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. -Testing is done regularly via our [GitLab Performance Tool (GPT)](https://gitlab.com/gitlab-org/quality/performance) and its dataset, which is available for anyone to use. +Testing is done regularly by using the [GitLab Performance Tool (GPT)](https://gitlab.com/gitlab-org/quality/performance) and its dataset, which is available for anyone to use. The results of this testing are [available publicly on the GPT wiki](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest). For more information on our testing strategy [refer to this section of the documentation](index.md#validation-and-test-results). -The load balancers used for testing were HAProxy for Linux package environments or equivalent Cloud Provider services via NGINX Ingress for Cloud Native Hybrids. Note that these selections do not represent a specific requirement or recommendation as most [reputable load balancers are expected to work](#configure-the-external-load-balancer). +The load balancers used for testing were HAProxy for Linux package environments or equivalent Cloud Provider services with NGINX Ingress for Cloud Native Hybrids. These selections do not represent a specific requirement or recommendation as most [reputable load balancers are expected to work](#configure-the-external-load-balancer). ## Set up components @@ -525,7 +525,7 @@ A reputable provider or solution should be used for this. [Google Cloud SQL](htt If you use a third party external service: -1. Note that the HA Linux package PostgreSQL setup encompasses PostgreSQL, PgBouncer and Consul. These components would no longer be required when using a third party external service. +1. The HA Linux package PostgreSQL setup encompasses PostgreSQL, PgBouncer and Consul. These components would no longer be required when using a third party external service. 1. Set up PostgreSQL according to the [database requirements document](../../install/requirements.md#database). 1. Set up a `gitlab` username with a password of your choice. The `gitlab` user @@ -546,9 +546,9 @@ replication and failover requires: - An [internal load balancer](#configure-the-internal-load-balancer) (TCP) to balance requests between the PgBouncer nodes. - [Database Load Balancing](../postgresql/database_load_balancing.md) enabled. - A local PgBouncer service to be configured on each PostgreSQL node. Note that this is separate from the main PgBouncer cluster that tracks the primary. + A local PgBouncer service to be configured on each PostgreSQL node. This is separate from the main PgBouncer cluster that tracks the primary. -The following IPs will be used as an example: +The following IPs are used as an example: - `10.6.0.21`: PostgreSQL primary - `10.6.0.22`: PostgreSQL secondary 1 @@ -2107,7 +2107,7 @@ the [HTTPS documentation](https://docs.gitlab.com/omnibus/settings/ssl/index.htm sudo gitlab-rake gitlab:db:configure ``` - Note that this requires the Rails node to be configured to connect to the primary database + This operation requires configuring the Rails node to connect to the primary database directly, [bypassing PgBouncer](../postgresql/pgbouncer.md#procedure-for-bypassing-pgbouncer). After migrations have completed, you must configure the node to pass through PgBouncer again. @@ -2407,9 +2407,9 @@ For further information on Webservice resource usage, see the Charts documentati ##### NGINX -It's also recommended deploying the NGINX controller pods across the Webservice nodes as a DaemonSet. This is to allow the controllers to scale dynamically with the Webservice pods they serve as well as take advantage of the higher network bandwidth larger machine types typically have. +It's also recommended deploying the NGINX controller pods across the Webservice nodes as a DaemonSet. This is to allow the controllers to scale dynamically with the Webservice pods they serve and take advantage of the higher network bandwidth larger machine types typically have. -Note that this isn't a strict requirement. The NGINX controller pods can be deployed as desired as long as they have enough resources to handle the web traffic. +This isn't a strict requirement. The NGINX controller pods can be deployed as desired as long as they have enough resources to handle the web traffic. #### Sidekiq diff --git a/doc/administration/reference_architectures/2k_users.md b/doc/administration/reference_architectures/2k_users.md index 8d1a9e02aaa..c66964d5159 100644 --- a/doc/administration/reference_architectures/2k_users.md +++ b/doc/administration/reference_architectures/2k_users.md @@ -40,7 +40,7 @@ For a full list of reference architectures, see 1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. See [Provide your own PostgreSQL instance](#provide-your-own-postgresql-instance) and [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information. 2. Can be optionally run on reputable third-party external PaaS Redis solutions. See [Provide your own Redis instance](#provide-your-own-redis-instance) and [Recommended cloud providers and services](index.md#recommended-cloud-providers-and-services) for more information. 3. Recommended to be run with a reputable third-party load balancer or service (LB PaaS). - Also note that sizing depends on selected Load Balancer as well as additional factors such as Network Bandwidth. Refer to [Load Balancers](index.md#load-balancers) for more information. + Sizing depends on selected Load Balancer and additional factors such as Network Bandwidth. See [Load Balancers](index.md#load-balancers) for more information. 4. Should be run on reputable Cloud Provider or Self Managed solutions. See [Configure the object storage](#configure-the-object-storage) for more information. 5. Gitaly specifications are based on the use of normal-sized repositories in good health. However, if you have large monorepos (larger than several gigabytes) this can **significantly** impact Git and Gitaly performance and an increase of specifications will likely be required. @@ -113,12 +113,12 @@ including CI and other workloads. If you have metrics to suggest that you have regularly higher throughput against the above endpoint targets, [large monorepos](index.md#large-monorepos) or notable [additional workloads](index.md#additional-workloads) these can notably impact the performance environment and [further adjustments may be required](index.md#scaling-an-environment). -If this applies to you, we strongly recommended referring to the linked documentation as well as 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 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. -Testing is done regularly via our [GitLab Performance Tool (GPT)](https://gitlab.com/gitlab-org/quality/performance) and its dataset, which is available for anyone to use. +Testing is done regularly by using our [GitLab Performance Tool (GPT)](https://gitlab.com/gitlab-org/quality/performance) and its dataset, which is available for anyone to use. The results of this testing are [available publicly on the GPT wiki](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest). For more information on our testing strategy [refer to this section of the documentation](index.md#validation-and-test-results). -The load balancers used for testing were HAProxy for Linux package environments or equivalent Cloud Provider services via NGINX Ingress for Cloud Native Hybrids. Note that these selections do not represent a specific requirement or recommendation as most [reputable load balancers are expected to work](#configure-the-external-load-balancer). +The load balancers used for testing were HAProxy for Linux package environments or equivalent Cloud Provider services with NGINX Ingress for Cloud Native Hybrids. These selections do not represent a specific requirement or recommendation as most [reputable load balancers are expected to work](#configure-the-external-load-balancer). ## Set up components @@ -272,7 +272,7 @@ A reputable provider or solution should be used for this. [Google Cloud SQL](htt If you use a third party external service: -1. Note that the HA Linux package PostgreSQL setup encompasses PostgreSQL, PgBouncer and Consul. All of these components would no longer be required when using a third party external service. +1. The HA Linux package PostgreSQL setup encompasses PostgreSQL, PgBouncer and Consul. All of these components would no longer be required when using a third party external service. 1. Set up PostgreSQL according to the [database requirements document](../../install/requirements.md#database). 1. Set up a `gitlab` username with a password of your choice. The `gitlab` user @@ -332,7 +332,7 @@ If you use a third party external service: 1. [Reconfigure GitLab](../restart_gitlab.md#reconfigure-a-linux-package-installation) for the changes to take effect. 1. Note the PostgreSQL node's IP address or hostname, port, and - plain text password. These will be necessary when configuring the + plain text password. These details are necessary when configuring the [GitLab application server](#configure-gitlab-rails) later. Advanced [configuration options](https://docs.gitlab.com/omnibus/settings/database.html) @@ -544,11 +544,11 @@ To configure the Gitaly server, on the server node you want to use for Gitaly: ### Gitaly TLS support -Gitaly supports TLS encryption. To be able to communicate -with a Gitaly instance that listens for secure connections you will need to use `tls://` URL +Gitaly supports TLS encryption. To communicate +with a Gitaly instance that listens for secure connections, you must use `tls://` URL scheme in the `gitaly_address` of the corresponding storage entry in the GitLab configuration. -You will need to bring your own certificates as this isn't provided automatically. +You must bring your own certificates as this isn't provided automatically. The certificate, or its certificate authority, must be installed on all Gitaly nodes (including the Gitaly node using the certificate) and on all client nodes that communicate with it following the procedure described in @@ -914,7 +914,7 @@ the [HTTPS documentation](https://docs.gitlab.com/omnibus/settings/ssl/index.htm sudo gitlab-rake gitlab:db:configure ``` - Note that this requires the Rails node to be configured to connect to the primary database + This operation requires configuring the Rails node to connect to the primary database directly, [bypassing PgBouncer](../postgresql/pgbouncer.md#procedure-for-bypassing-pgbouncer). After migrations have completed, you must configure the node to pass through PgBouncer again. @@ -1123,7 +1123,7 @@ the overall makeup as desired as long as the minimum CPU and Memory requirements [Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine) and [Amazon Elastic Kubernetes Service (EKS)](https://aws.amazon.com/eks/). Other Kubernetes services may also work, but your mileage may vary. - GCP and AWS examples of how to reach the Target Node Pool Total are given for convenience. These sizes are used in performance testing but following the example is not required. Different node pool designs can be used as desired as long as the targets are met, and all pods can deploy. - The [Webservice](#webservice) and [Sidekiq](#sidekiq) target node pool totals are given for GitLab components only. Additional resources are required for the chosen Kubernetes provider's system processes. The given examples take this into account. -- The [Supporting](#supporting) target node pool total is given generally to accommodate several resources for supporting the GitLab deployment as well as any additional deployments you may wish to make depending on your requirements. Similar to the other node pools, the chosen Kubernetes provider's system processes also require resources. The given examples take this into account. +- The [Supporting](#supporting) target node pool total is given generally to accommodate several resources for supporting the GitLab deployment and any additional deployments you may wish to make depending on your requirements. Similar to the other node pools, the chosen Kubernetes provider's system processes also require resources. The given examples take this into account. - In production deployments, it's not required to assign pods to specific nodes. However, it is recommended to have several nodes in each pool spread across different availability zones to align with resilient cloud architecture practices. - Enabling autoscaling, such as Cluster Autoscaler, for efficiency reasons is encouraged, but it's generally recommended targeting a floor of 75% for Webservice and Sidekiq pods to ensure ongoing performance. @@ -1197,16 +1197,16 @@ Each Webservice pod (Puma and Workhorse) is recommended to be run with the follo - 5 GB memory (request) - 7 GB memory (limit) -For 40 RPS or 2,000 users we recommend a total Puma worker count of around 12 so in turn it's recommended to run at +For 40 RPS or 2,000 users, we recommend a total Puma worker count of around 12 so in turn it's recommended to run at least 3 Webservice pods. For further information on Webservice resource usage, see the Charts documentation on [Webservice resources](https://docs.gitlab.com/charts/charts/gitlab/webservice/#resources). ##### NGINX -It's also recommended deploying the NGINX controller pods across the Webservice nodes as a DaemonSet. This is to allow the controllers to scale dynamically with the Webservice pods they serve as well as take advantage of the higher network bandwidth larger machine types typically have. +It's also recommended deploying the NGINX controller pods across the Webservice nodes as a DaemonSet. This allows the controllers to scale dynamically with the Webservice pods they serve, and takes advantage of the higher network bandwidth larger machine types typically have. -Note that this isn't a strict requirement. The NGINX controller pods can be deployed as desired as long as they have enough resources to handle the web traffic. +This isn't a strict requirement. The NGINX controller pods can be deployed as desired as long as they have enough resources to handle the web traffic. #### Sidekiq diff --git a/doc/administration/reference_architectures/3k_users.md b/doc/administration/reference_architectures/3k_users.md index af7eed7489d..fffc3165325 100644 --- a/doc/administration/reference_architectures/3k_users.md +++ b/doc/administration/reference_architectures/3k_users.md @@ -48,7 +48,7 @@ For a full list of reference architectures, see 1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. See [Provide your own PostgreSQL instance](#provide-your-own-postgresql-instance) for more information. 2. Can be optionally run on reputable third-party external PaaS Redis solutions. See [Provide your own Redis instance](#provide-your-own-redis-instance) for more information. 3. Recommended to be run with a reputable third-party load balancer or service (LB PaaS) which can provide HA capabilities. - Also note that sizing depends on selected Load Balancer as well as additional factors such as Network Bandwidth. Refer to [Load Balancers](index.md#load-balancers) for more information. + Sizing depends on selected Load Balancer and additional factors such as Network Bandwidth. Refer to [Load Balancers](index.md#load-balancers) for more information. 4. Should be run on reputable Cloud Provider or Self Managed solutions. See [Configure the object storage](#configure-the-object-storage) for more information. 5. Gitaly Cluster provides the benefits of fault tolerance, but comes with additional complexity of setup and management. Review the existing [technical limitations and considerations before deploying Gitaly Cluster](../gitaly/index.md#before-deploying-gitaly-cluster). If you want sharded Gitaly, use the same specs listed above for `Gitaly`. @@ -165,12 +165,12 @@ including CI and other workloads. If you have metrics to suggest that you have regularly higher throughput against the above endpoint targets, [large monorepos](index.md#large-monorepos) or notable [additional workloads](index.md#additional-workloads) these can notably impact the performance environment and [further adjustments may be required](index.md#scaling-an-environment). -If this applies to you, we strongly recommended referring to the linked documentation as well as 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 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. -Testing is done regularly via our [GitLab Performance Tool (GPT)](https://gitlab.com/gitlab-org/quality/performance) and its dataset, which is available for anyone to use. +Testing is done regularly by using our [GitLab Performance Tool (GPT)](https://gitlab.com/gitlab-org/quality/performance) and its dataset, which is available for anyone to use. The results of this testing are [available publicly on the GPT wiki](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest). For more information on our testing strategy [refer to this section of the documentation](index.md#validation-and-test-results). -The load balancers used for testing were HAProxy for Linux package environments or equivalent Cloud Provider services via NGINX Ingress for Cloud Native Hybrids. Note that these selections do not represent a specific requirement or recommendation as most [reputable load balancers are expected to work](#configure-the-external-load-balancer). +The load balancers used for testing were HAProxy for Linux package environments or equivalent Cloud Provider services with NGINX Ingress for Cloud Native Hybrids. These selections do not represent a specific requirement or recommendation as most [reputable load balancers are expected to work](#configure-the-external-load-balancer). ## Set up components @@ -511,7 +511,7 @@ A reputable provider or solution should be used for this. [Google Cloud SQL](htt If you use a third party external service: -1. Note that the HA Linux package PostgreSQL setup encompasses PostgreSQL, PgBouncer and Consul. All of these components would no longer be required when using a third party external service. +1. The HA Linux package PostgreSQL setup encompasses PostgreSQL, PgBouncer and Consul. All of these components would no longer be required when using a third party external service. 1. Set up PostgreSQL according to the [database requirements document](../../install/requirements.md#database). 1. Set up a `gitlab` username with a password of your choice. The `gitlab` user @@ -532,7 +532,7 @@ replication and failover requires: - An [internal load balancer](#configure-the-internal-load-balancer) (TCP) to balance requests between the PgBouncer nodes. - [Database Load Balancing](../postgresql/database_load_balancing.md) enabled. - A local PgBouncer service to be configured on each PostgreSQL node. Note that this is separate from the main PgBouncer cluster that tracks the primary. + A local PgBouncer service to be configured on each PostgreSQL node. This is separate from the main PgBouncer cluster that tracks the primary. The following IPs are used as an example: @@ -1965,7 +1965,7 @@ the [HTTPS documentation](https://docs.gitlab.com/omnibus/settings/ssl/index.htm gitlab-rake gitlab:db:configure ``` - Note that this requires the Rails node to be configured to connect to the primary database + This operation requires configuring the Rails node to connect to the primary database directly, [bypassing PgBouncer](../postgresql/pgbouncer.md#procedure-for-bypassing-pgbouncer). After migrations have completed, you must configure the node to pass through PgBouncer again. @@ -2197,7 +2197,7 @@ services where applicable): 1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. See [Provide your own PostgreSQL instance](#provide-your-own-postgresql-instance) for more information. 2. Can be optionally run on reputable third-party external PaaS Redis solutions. See [Provide your own Redis instance](#provide-your-own-redis-instance) for more information. 3. Recommended to be run with a reputable third-party load balancer or service (LB PaaS) which can provide HA capabilities. - Also note that sizing depends on selected Load Balancer as well as additional factors such as Network Bandwidth. Refer to [Load Balancers](index.md#load-balancers) for more information. + Sizing depends on selected Load Balancer and additional factors such as Network Bandwidth. Refer to [Load Balancers](index.md#load-balancers) for more information. 4. Should be run on reputable Cloud Provider or Self Managed solutions. See [Configure the object storage](#configure-the-object-storage) for more information. 5. Gitaly Cluster provides the benefits of fault tolerance, but comes with additional complexity of setup and management. Review the existing [technical limitations and considerations before deploying Gitaly Cluster](../gitaly/index.md#before-deploying-gitaly-cluster). If you want sharded Gitaly, use the same specs listed above for `Gitaly`. @@ -2295,9 +2295,9 @@ For further information on Webservice resource usage, see the Charts documentati ##### NGINX -It's also recommended deploying the NGINX controller pods across the Webservice nodes as a DaemonSet. This is to allow the controllers to scale dynamically with the Webservice pods they serve as well as take advantage of the higher network bandwidth larger machine types typically have. +It's also recommended deploying the NGINX controller pods across the Webservice nodes as a DaemonSet. This allows the controllers to scale dynamically with the Webservice pods they serve, and takes advantage of the higher network bandwidth larger machine types typically have. -Note that this isn't a strict requirement. The NGINX controller pods can be deployed as desired as long as they have enough resources to handle the web traffic. +This isn't a strict requirement. The NGINX controller pods can be deployed as desired as long as they have enough resources to handle the web traffic. #### Sidekiq diff --git a/doc/administration/reference_architectures/50k_users.md b/doc/administration/reference_architectures/50k_users.md index 8ec49da1d1c..052a9786300 100644 --- a/doc/administration/reference_architectures/50k_users.md +++ b/doc/administration/reference_architectures/50k_users.md @@ -169,12 +169,12 @@ including CI and other workloads. If you have metrics to suggest that you have regularly higher throughput against the above endpoint targets, [large monorepos](index.md#large-monorepos) or notable [additional workloads](index.md#additional-workloads) these can notably impact the performance environment and [further adjustments may be required](index.md#scaling-an-environment). -If this applies to you, we strongly recommended referring to the linked documentation as well as 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 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. -Testing is done regularly via our [GitLab Performance Tool (GPT)](https://gitlab.com/gitlab-org/quality/performance) and its dataset, which is available for anyone to use. +Testing is done regularly by using the [GitLab Performance Tool (GPT)](https://gitlab.com/gitlab-org/quality/performance) and its dataset, which is available for anyone to use. The results of this testing are [available publicly on the GPT wiki](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest). For more information on our testing strategy [refer to this section of the documentation](index.md#validation-and-test-results). -The load balancers used for testing were HAProxy for Linux package environments or equivalent Cloud Provider services via NGINX Ingress for Cloud Native Hybrids. Note that these selections do not represent a specific requirement or recommendation as most [reputable load balancers are expected to work](#configure-the-external-load-balancer). +The load balancers used for testing were HAProxy for Linux package environments or equivalent Cloud Provider services with NGINX Ingress for Cloud Native Hybrids. These selections do not represent a specific requirement or recommendation as most [reputable load balancers are expected to work](#configure-the-external-load-balancer). ## Set up components @@ -529,7 +529,7 @@ A reputable provider or solution should be used for this. [Google Cloud SQL](htt If you use a third party external service: -1. Note that the HA Linux package PostgreSQL setup encompasses PostgreSQL, PgBouncer and Consul. All of these components would no longer be required when using a third party external service. +1. The HA Linux package PostgreSQL setup encompasses PostgreSQL, PgBouncer and Consul. All of these components would no longer be required when using a third party external service. 1. Set up PostgreSQL according to the [database requirements document](../../install/requirements.md#database). 1. Set up a `gitlab` username with a password of your choice. The `gitlab` user @@ -550,7 +550,7 @@ replication and failover requires: - An [internal load balancer](#configure-the-internal-load-balancer) (TCP) to balance requests between the PgBouncer nodes. - [Database Load Balancing](../postgresql/database_load_balancing.md) enabled. - A local PgBouncer service to be configured on each PostgreSQL node. Note that this is separate from the main PgBouncer cluster that tracks the primary. + A local PgBouncer service to be configured on each PostgreSQL node. This is separate from the main PgBouncer cluster that tracks the primary. The following IPs will be used as an example: @@ -2121,7 +2121,7 @@ the [HTTPS documentation](https://docs.gitlab.com/omnibus/settings/ssl/index.htm sudo gitlab-rake gitlab:db:configure ``` - Note that this requires the Rails node to be configured to connect to the primary database + This operation requires configuring the Rails node to connect to the primary database directly, [bypassing PgBouncer](../postgresql/pgbouncer.md#procedure-for-bypassing-pgbouncer). After migrations have completed, you must configure the node to pass through PgBouncer again. @@ -2421,9 +2421,9 @@ For further information on Webservice resource usage, see the Charts documentati ##### NGINX -It's also recommended deploying the NGINX controller pods across the Webservice nodes as a DaemonSet. This is to allow the controllers to scale dynamically with the Webservice pods they serve as well as take advantage of the higher network bandwidth larger machine types typically have. +It's also recommended deploying the NGINX controller pods across the Webservice nodes as a DaemonSet. This is to allow the controllers to scale dynamically with the Webservice pods they serve and take advantage of the higher network bandwidth larger machine types typically have. -Note that this isn't a strict requirement. The NGINX controller pods can be deployed as desired as long as they have enough resources to handle the web traffic. +This isn't a strict requirement. The NGINX controller pods can be deployed as desired as long as they have enough resources to handle the web traffic. #### Sidekiq diff --git a/doc/administration/reference_architectures/5k_users.md b/doc/administration/reference_architectures/5k_users.md index 1c9d61a935f..c04feb81e7a 100644 --- a/doc/administration/reference_architectures/5k_users.md +++ b/doc/administration/reference_architectures/5k_users.md @@ -48,7 +48,7 @@ specifically the [Before you start](index.md#before-you-start) and [Deciding whi 1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. See [Provide your own PostgreSQL instance](#provide-your-own-postgresql-instance) for more information. 2. Can be optionally run on reputable third-party external PaaS Redis solutions. See [Provide your own Redis instance](#provide-your-own-redis-instance) for more information. 3. Recommended to be run with a reputable third-party load balancer or service (LB PaaS) which can provide HA capabilities. - Also note that sizing depends on selected Load Balancer as well as additional factors such as Network Bandwidth. Refer to [Load Balancers](index.md#load-balancers) for more information. + Also, the sizing depends on selected Load Balancer and additional factors such as Network Bandwidth. Refer to [Load Balancers](index.md#load-balancers) for more information. 4. Should be run on reputable Cloud Provider or Self Managed solutions. See [Configure the object storage](#configure-the-object-storage) for more information. 5. Gitaly Cluster provides the benefits of fault tolerance, but comes with additional complexity of setup and management. Review the existing [technical limitations and considerations before deploying Gitaly Cluster](../gitaly/index.md#before-deploying-gitaly-cluster). If you want sharded Gitaly, use the same specs listed above for `Gitaly`. @@ -165,12 +165,12 @@ including CI and other workloads. If you have metrics to suggest that you have regularly higher throughput against the above endpoint targets, [large monorepos](index.md#large-monorepos) or notable [additional workloads](index.md#additional-workloads) these can notably impact the performance environment and [further adjustments may be required](index.md#scaling-an-environment). -If this applies to you, we strongly recommended referring to the linked documentation as well as 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 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. -Testing is done regularly via our [GitLab Performance Tool (GPT)](https://gitlab.com/gitlab-org/quality/performance) and its dataset, which is available for anyone to use. +Testing is done regularly by using the [GitLab Performance Tool (GPT)](https://gitlab.com/gitlab-org/quality/performance) and its dataset, which is available for anyone to use. The results of this testing are [available publicly on the GPT wiki](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest). For more information on our testing strategy [refer to this section of the documentation](index.md#validation-and-test-results). -The load balancers used for testing were HAProxy for Linux package environments or equivalent Cloud Provider services via NGINX Ingress for Cloud Native Hybrids. Note that these selections do not represent a specific requirement or recommendation as most [reputable load balancers are expected to work](#configure-the-external-load-balancer). +The load balancers used for testing were HAProxy for Linux package environments or equivalent Cloud Provider services with NGINX Ingress for Cloud Native Hybrids. These selections do not represent a specific requirement or recommendation as most [reputable load balancers are expected to work](#configure-the-external-load-balancer). ## Set up components @@ -511,7 +511,7 @@ A reputable provider or solution should be used for this. [Google Cloud SQL](htt If you use a third party external service: -1. Note that the HA Linux package PostgreSQL setup encompasses PostgreSQL, PgBouncer and Consul. All of these components would no longer be required when using a third party external service. +1. The HA Linux package PostgreSQL setup encompasses PostgreSQL, PgBouncer and Consul. All of these components would no longer be required when using a third party external service. 1. Set up PostgreSQL according to the [database requirements document](../../install/requirements.md#database). 1. Set up a `gitlab` username with a password of your choice. The `gitlab` user @@ -532,7 +532,7 @@ replication and failover requires: - An [internal load balancer](#configure-the-internal-load-balancer) (TCP) to balance requests between the PgBouncer nodes. - [Database Load Balancing](../postgresql/database_load_balancing.md) enabled. - A local PgBouncer service to be configured on each PostgreSQL node. Note that this is separate from the main PgBouncer cluster that tracks the primary. + A local PgBouncer service to be configured on each PostgreSQL node. This is separate from the main PgBouncer cluster that tracks the primary. The following IPs are used as an example: @@ -1965,7 +1965,7 @@ the [HTTPS documentation](https://docs.gitlab.com/omnibus/settings/ssl/index.htm gitlab-rake gitlab:db:configure ``` - Note that this requires the Rails node to be configured to connect to the primary database + This operation requires configuring the Rails node to connect to the primary database directly, [bypassing PgBouncer](../postgresql/pgbouncer.md#procedure-for-bypassing-pgbouncer). After migrations have completed, you must configure the node to pass through PgBouncer again. @@ -2170,7 +2170,7 @@ services where applicable): 1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. See [Provide your own PostgreSQL instance](#provide-your-own-postgresql-instance) for more information. 2. Can be optionally run on reputable third-party external PaaS Redis solutions. See [Provide your own Redis instance](#provide-your-own-redis-instance) for more information. 3. Recommended to be run with a reputable third-party load balancer or service (LB PaaS). - Also note that sizing depends on selected Load Balancer as well as additional factors such as Network Bandwidth. Refer to [Load Balancers](index.md#load-balancers) for more information. + Also, the sizing depends on selected Load Balancer and additional factors such as Network Bandwidth. Refer to [Load Balancers](index.md#load-balancers) for more information. 4. Should be run on reputable Cloud Provider or Self Managed solutions. See [Configure the object storage](#configure-the-object-storage) for more information. 5. Gitaly Cluster provides the benefits of fault tolerance, but comes with additional complexity of setup and management. Review the existing [technical limitations and considerations before deploying Gitaly Cluster](../gitaly/index.md#before-deploying-gitaly-cluster). If you want sharded Gitaly, use the same specs listed above for `Gitaly`. @@ -2268,9 +2268,9 @@ For further information on Webservice resource usage, see the Charts documentati ##### NGINX -It's also recommended deploying the NGINX controller pods across the Webservice nodes as a DaemonSet. This is to allow the controllers to scale dynamically with the Webservice pods they serve as well as take advantage of the higher network bandwidth larger machine types typically have. +It's also recommended deploying the NGINX controller pods across the Webservice nodes as a DaemonSet. It allows the controllers to scale dynamically with the Webservice pods they serve and take advantage of the higher network bandwidth larger machine types typically have. -Note that this isn't a strict requirement. The NGINX controller pods can be deployed as desired as long as they have enough resources to handle the web traffic. +This isn't a strict requirement. The NGINX controller pods can be deployed as desired as long as they have enough resources to handle the web traffic. #### Sidekiq diff --git a/doc/administration/reference_architectures/index.md b/doc/administration/reference_architectures/index.md index 718675c7593..0dc8ccef4cf 100644 --- a/doc/administration/reference_architectures/index.md +++ b/doc/administration/reference_architectures/index.md @@ -216,11 +216,11 @@ CPU targets being the lowest common denominator to ensure the widest range of co - 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 as well as 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, but it is expected that the target CPUs above should 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 as well as 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) where applicable. NOTE: Any "burstable" instance types are not recommended due to inconsistent performance. @@ -251,10 +251,10 @@ See [Recommended cloud providers and services](index.md#recommended-cloud-provid The reference 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, as well as 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 through to the underlying infrastructure. WARNING: -If this applies to you, we strongly recommended referring to the linked documentation as well as 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 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. 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: @@ -415,7 +415,7 @@ Additionally, the following cloud provider services are recommended for use as p If you choose to use a third party external service: -1. Note that the HA Linux package PostgreSQL setup encompasses PostgreSQL, PgBouncer and Consul. All of these components would no longer be required when using a third party external service. +1. The HA Linux package PostgreSQL setup encompasses PostgreSQL, PgBouncer and Consul. All of these components would no longer be required when using a third party external service. 1. The number of nodes required to achieve HA may differ depending on the service compared to the Linux package and doesn't need to match accordingly. 1. It's recommended in general to enable Read Replicas for [Database Load Balancing](../postgresql/database_load_balancing.md) if possible, matching the node counts for the standard Linux package deployment. This recommendation is especially so for larger environments (over 200 RPS / 10k users). 1. Ensure that if a pooler is offered as part of the service that it can handle the total load without bottlenecking. @@ -433,7 +433,7 @@ Several database cloud provider services are known not to support the above or h ### Recommendation notes for the Redis services -[When selecting to use an external Redis service](../redis/replication_and_failover_external.md#redis-as-a-managed-service-in-a-cloud-provider), it should run a standard, performant, and supported version. Note that this specifically must not be run in [Cluster mode](../../install/requirements.md#redis) as this is unsupported by GitLab. +[When selecting to use an external Redis service](../redis/replication_and_failover_external.md#redis-as-a-managed-service-in-a-cloud-provider), it should run a standard, performant, and supported version. This specifically must not be run in [Cluster mode](../../install/requirements.md#redis) as this is unsupported by GitLab. Redis is primarily single threaded. For environments targeting up to 200 RPS / 10,000 users or higher, separate out the instances as specified into Cache and Persistent data to achieve optimum performance at this scale. @@ -498,7 +498,7 @@ remain compliant. ### Why we perform the tests The Quality Department has a focus on measuring and improving the performance -of GitLab, as well as creating and validating reference architectures that +of GitLab, and creating and validating reference architectures that self-managed customers can rely on as performant configurations. For more information, see our [handbook page](https://handbook.gitlab.com/handbook/engineering/infrastructure/test-platform/performance-and-scalability/). @@ -513,7 +513,7 @@ Testing occurs against all reference architectures and cloud providers in an aut Network latency on the test environments between components on all Cloud Providers were measured at <5 ms. This is shared as an observation and not as an implicit recommendation. We aim to have a "test smart" approach where architectures tested have a good range that can also apply to others. Testing focuses on a 10k Linux package -installation on GCP as the testing has shown this is a good bellwether for the other architectures and cloud providers as well as Cloud Native Hybrids. +installation on GCP as the testing has shown this is a good bellwether for the other architectures and cloud providers and Cloud Native Hybrids. The Standard Reference Architectures are designed to be platform-agnostic, with everything being run on VMs through [the Linux package](https://docs.gitlab.com/omnibus/). While testing occurs primarily on GCP, ad-hoc testing has shown that they perform similarly on hardware with equivalent specs on other Cloud Providers or if run on premises (bare-metal). @@ -635,9 +635,9 @@ table.test-coverage th { ## Cost calculator templates -As a starting point, the following table lists initial compute calculator cost templates for the different reference architectures across GCP, AWS, and Azure via each cloud provider's official calculator. +As a starting point, the following table lists initial compute calculator cost templates for the different reference architectures across GCP, AWS, and Azure by using each cloud provider's official calculator. -However, please be aware of the following caveats: +However, be aware of the following caveats: - These are only rough estimate compute templates for the Linux package architectures. - They do not take into account dynamic elements such as disk, network or object storage - Which can notably impact costs. @@ -710,7 +710,7 @@ To get an accurate estimate of costs for your specific environment you must take Maintaining a Reference Architecture environment is generally the same as any other GitLab environment is generally covered in other sections of this documentation. -In this section you'll find links to documentation for relevant areas as well as any specific Reference Architecture notes. +In this section you'll find links to documentation for relevant areas and any specific Reference Architecture notes. ### Scaling an environment @@ -719,7 +719,7 @@ The Reference Architectures have been designed as a starting point and are elast NOTE: If you're seeing a component continuously exhausting it's given resources it's strongly recommended for you to reach out to our [Support team](https://about.gitlab.com/support/) before performing any scaling. This is especially so if you're planning to scale any component significantly. -For most components vertical and horizontal scaling can be applied as normal. However, before doing so though please be aware of the below caveats: +For most components vertical and horizontal scaling can be applied as usual. However, before doing so, be aware of the below caveats: - When scaling Puma or Sidekiq vertically the amount of workers will need to be adjusted to use the additional specs. Puma will be scaled automatically on the next reconfigure but Sidekiq will need [its configuration changed beforehand](../sidekiq/extra_sidekiq_processes.md#start-multiple-processes). - Redis and PgBouncer are primarily single threaded. If these components are seeing CPU exhaustion they may need to be scaled out horizontally. @@ -739,13 +739,13 @@ The following components can impact others when they have been significantly sca - Puma and Sidekiq - Notable scale ups of either Puma or Sidekiq workers will result in higher concurrent connections to the internal load balancer, PostgreSQL (via PgBouncer if present), Gitaly (via Praefect if present) and Redis respectively. - Redis is primarily single threaded and in some cases may need to be split up into different instances (Cache / Persistent) if the increased throughput causes CPU exhaustion if a combined cluster is currently being used. - - PgBouncer is also single threaded but note that a scale out will result in a new pool being added that in turn will increase total connections to Postgres. It's strongly recommended to only do this if you have experience in managing Postgres connections and to seek assistance if in doubt. + - PgBouncer is also single threaded but a scale out might result in a new pool being added that in turn might increase the total connections to Postgres. It's strongly recommended to only do this if you have experience in managing Postgres connections and to seek assistance if in doubt. - Gitaly Cluster / PostgreSQL - A notable scale out of additional nodes can have a detrimental effect on the HA system and performance due to increased replication calls to the primary node. #### Scaling from a non-HA to an HA architecture While in most cases vertical scaling is only required to increase an environment's resources, if you are moving to an HA environment -additional steps will be required for the following components to switch over to their HA forms respectively by following the given +additional steps are required for the following components to switch over to their HA forms respectively by following the given documentation for each as follows - [Redis to multi-node Redis w/ Redis Sentinel](../redis/replication_and_failover.md#switching-from-an-existing-single-machine-installation) @@ -764,9 +764,9 @@ You should upgrade a Reference Architecture in the same order as you created it. ### Monitoring -There are numerous options available to monitor your infrastructure, as well as [GitLab itself](../monitoring/index.md), and you should refer to your selected monitoring solution's documentation for more information. +There are numerous options available to monitor your infrastructure, and [GitLab itself](../monitoring/index.md), and you should refer to your selected monitoring solution's documentation for more information. -Of note, the GitLab application is bundled with [Prometheus as well as various Prometheus compatible exporters](../monitoring/prometheus/index.md) that could be hooked into your solution. +Of note, the GitLab application is bundled with [Prometheus and various Prometheus compatible exporters](../monitoring/prometheus/index.md) that could be hooked into your solution. ## Update history @@ -790,7 +790,7 @@ You can find a full history of changes [on the GitLab project](https://gitlab.co **2023:** - [2023-12-12](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/139557): Updated notes on Load Balancers to be more reflective that any reputable offering is expected to work. -- [2023-11-03](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/133457): Expanded details on what each Reference Architecture is designed for, the testing methodology used as well as added details on how to scale environments. +- [2023-11-03](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/133457): Expanded details on what each Reference Architecture is designed for, the testing methodology used and added details on how to scale environments. - [2023-11-03](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/134518): Added expanded notes on disk types, object storage and monitoring. - [2023-10-25](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/134518): Adjusted Sidekiq configuration example to use Linux Package role. - [2023-10-15](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/133835): Adjusted the Sidekiq recommendations to include a separate node for 2k and tweaks to instance type and counts for 3k and 5k. @@ -802,7 +802,7 @@ You can find a full history of changes [on the GitLab project](https://gitlab.co - [2023-08-30](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/130470): Expanded section on Geo under the Decision Tree. - [2023-08-08](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/128529): Switch config example to use the Sidekiq role for Linux package. - [2023-08-03](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/128374): Fixed an AWS Machine type typo for the 50k architecture. -- [2023-11-03](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/133457): Expand details on what each Reference Architecture is designed for, the testing methodology used as well as added details on how to scale environments. +- [2023-11-03](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/133457): Expand details on what each Reference Architecture is designed for, the testing methodology used and added details on how to scale environments. - [2023-11-03](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/134518): Add expanded notes on disk types, object storage and monitoring. - [2023-10-25](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/134518): Adjust Sidekiq configuration example to use Linux Package role. - [2023-10-15](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/133835): Adjust the Sidekiq recommendations to include a separate node for 2k and tweaks to instance type and counts for 3k and 5k. @@ -846,7 +846,7 @@ You can find a full history of changes [on the GitLab project](https://gitlab.co - [2022-09-22](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98263): Add explicit step to enable Incremental Logging when only Object Storage is being used. - [2022-09-22](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98184): Expand guidance on recommended cloud providers and services. - [2022-09-09](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97245): Expand Object Storage guidance and updated that NFS support for Git data ends with `15.6`. -- [2022-08-24](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96150): Add clearer note that Gitaly Cluster is not supported in Kubernetes. +- [2022-08-24](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96150): Add a clearer note that Gitaly Cluster is not supported in Kubernetes. - [2022-08-24](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96021): Add section on supported CPUs and types. - [2022-08-18](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95713): Update architecture tables to be clearer for Object Storage support. - [2022-08-17](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95185): Increase Cloud Native Hybrid pool specs for 2k architecture to ensure enough resources present for pods. Also increased Sidekiq worker count. @@ -862,7 +862,7 @@ You can find a full history of changes [on the GitLab project](https://gitlab.co - [2022-04-08](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/84389): Add cost estimates for AWS and Azure. - [2022-04-06](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/84483): Update configuration examples for most components to be correctly included for Prometheus monitoring auto discovery. - [2022-03-30](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81538): Expand validation and testing result's section with more clearly language and more detail. -- [2022-03-21](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/83019): Add note that additional specs may be needed for Gitaly in some scenarios. +- [2022-03-21](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/83019): Add a note that additional specs may be needed for Gitaly in some scenarios. - [2022-03-04](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/82087): Add guidance for preventing the GitLab KAS service running on nodes where not required. - [2022-03-01](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81814): Fix a typo for Praefect TLS port in configuration examples. - [2022-02-22](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81247): Add guidance to enable the Gitaly Pack-objects cache. @@ -883,7 +883,7 @@ You can find a full history of changes [on the GitLab project](https://gitlab.co - [2021-11-24](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74612): Add recommendations for Database Load Balancing. - [2021-11-04](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73634): Add more detail about testing targets used for the architectures. - [2021-10-13](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72052): Add guidance around optionally enabling Incremental Logging via Redis. -- [2021-10-07](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71784): Update Sidekiq config to include required `external_url` setting. +- [2021-10-07](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71784): Update Sidekiq configuration to include required `external_url` setting. - [2021-10-02](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71576): Expand guidance around Gitaly Cluster and Gitaly Sharded. - [2021-09-29](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70625): Add note on what Cloud Native Hybrid architecture to use with small user counts. - [2021-09-27](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70602): Change guidance to now co-locate Redis Sentinel beside Redis on the same node. diff --git a/doc/api/group_service_accounts.md b/doc/api/group_service_accounts.md new file mode 100644 index 00000000000..394887b0741 --- /dev/null +++ b/doc/api/group_service_accounts.md @@ -0,0 +1,208 @@ +--- +stage: Govern +group: Authentication +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments +--- + +# Group service accounts + +DETAILS: +**Tier:** Premium, Ultimate +**Offering:** GitLab.com, Self-managed, GitLab Dedicated + +Interact with [service accounts](../user/profile/service_accounts.md) by using the REST API. + +## List service account users + +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/416729) in GitLab 17.1. + +Prerequisites: + +- You must be an administrator of the self-managed instance, or have the Owner role for the group. + +Lists all service account users that are provisioned by group. + +This function takes pagination parameters `page` and `per_page` to restrict the list of users. + +```plaintext +GET /groups/:id/service_accounts +``` + +Parameters: + +| Attribute | Type | Required | Description | +|:-------------|:---------|:-----------|:----------------------------------------------------------------| +| `id` | integer/string | yes | The ID or [URL-encoded path of the target group](rest/index.md#namespaced-path-encoding). | +| `order_by` | string | no | Orders list of users by `username` or `id`. Default is `id`. | +| `sort` | string | no | Specifies sorting by `asc` or `desc`. Default is `desc`. | + +Example request: + +```shell +curl --request GET --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/345/service_accounts" +``` + +Example response: + +```json +[ + + { + "id": 57, + "username": "service_account_group_345_", + "name": "Service account user" + }, + { + "id": 58, + "username": "service_account_group_346_", + "name": "Service account user" + } +] +``` + +## Create a service account user + +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/407775) in GitLab 16.1. +> - Ability to specify a username or name was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/144841) in GitLab 16.10. + +Creates a service account user. + +This API endpoint works on top-level groups only. It does not work on subgroups. + +```plaintext +POST /groups/:id/service_accounts +``` + +Supported attributes: + +| Attribute | Type | Required | Description | +|:---------------------------|:---------------|:--------------------------|:-------------------------------------------------------------------------------| +| `id` | integer/string | yes | The ID or [URL-encoded path of the target group](rest/index.md#namespaced-path-encoding). | +| `name` | string | no | The name of the user. If not specified, the default `Service account user` name is used. | +| `username` | string | no | The username of the user. If not specified, it's automatically generated. | + +Example request: + +```shell +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/345/service_accounts" +``` + +Example response: + +```json +{ + "id": 57, + "username": "service_account_group_345_6018816a18e515214e0c34c2b33523fc", + "name": "Service account user" +} +``` + +## Delete a service account user + +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/416729) in GitLab 17.1. + +Deletes a service account user. + +This API endpoint works on top-level groups only. It does not work on subgroups. + +```plaintext +DELETE /groups/:id/service_accounts/:user_id +``` + +Parameters: + +| Attribute | Type | Required | Description | +|:---------------------------|:---------------|:--------------------------|:-------------------------------------------------------------------------------| +| `id` | integer/string | yes | The ID or [URL-encoded path of the target group](rest/index.md#namespaced-path-encoding). | +| `user_id` | integer | yes | The ID of a service account user. | +| `hard_delete` | boolean | no | If true, contributions that would usually be [moved to a Ghost User](../user/profile/account/delete_account.md#associated-records) are instead deleted, as well as groups owned solely by this service account user. | + +Example request: + +```shell +curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/345/service_accounts/181" +``` + +## Create a personal access token for a service account user + +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/406781) in GitLab 16.1. + +This API endpoint works on top-level groups only. It does not work on subgroups. + +```plaintext +POST /groups/:id/service_accounts/:user_id/personal_access_tokens +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --------- | --------------- | -------- | ----------- | +| `id` | integer/string | yes | The ID or [URL-encoded path of the target group](rest/index.md#namespaced-path-encoding). | +| `user_id` | integer | yes | The ID of a service account user. | +| `name` | string | yes | The name of the personal access token. | +| `scopes` | array | yes | Array of scopes of the personal access token. See [personal access token scopes](../user/profile/personal_access_tokens.md#personal-access-token-scopes) for possible values. | +| `expires_at` | date | no | The personal access token expiry date. When left blank, the token follows the [standard rule of expiry for personal access tokens](../user/profile/personal_access_tokens.md#when-personal-access-tokens-expire). | + +Example request: + +```shell +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/35/service_accounts/71/personal_access_tokens" --data "scopes[]=api,read_user,read_repository" --data "name=service_accounts_token" +``` + +Example response: + +```json +{ + "id":6, + "name":"service_accounts_token", + "revoked":false, + "created_at":"2023-06-13T07:47:13.900Z", + "scopes":["api"], + "user_id":71, + "last_used_at":null, + "active":true, + "expires_at":"2024-06-12", + "token":"" +} +``` + +## Rotate a personal access token for a service account user + +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/406781) in GitLab 16.1. + +This API endpoint works on top-level groups only. It does not work on subgroups. + +```plaintext +POST /groups/:id/service_accounts/:user_id/personal_access_tokens/:token_id/rotate +``` + +Parameters: + +| Attribute | Type | Required | Description | +| --------- | --------------- | -------- | ----------- | +| `id` | integer/string | yes | The ID or [URL-encoded path of the target group](rest/index.md#namespaced-path-encoding). | +| `user_id` | integer | yes | The ID of the service account user. | +| `token_id` | integer | yes | The ID of the token. | + +Example request: + +```shell +curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/35/service_accounts/71/personal_access_tokens/6/rotate" +``` + +Example response: + +```json +{ + "id":7, + "name":"service_accounts_token", + "revoked":false, + "created_at":"2023-06-13T07:54:49.962Z", + "scopes":["api"], + "user_id":71, + "last_used_at":null, + "active":true, + "expires_at":"2023-06-20", + "token":"" +} +``` diff --git a/doc/api/groups.md b/doc/api/groups.md index 5360d01aeb4..1d663265932 100644 --- a/doc/api/groups.md +++ b/doc/api/groups.md @@ -1610,186 +1610,6 @@ Example response: ] ``` -## Service Accounts - -DETAILS: -**Tier:** Premium, Ultimate -**Offering:** GitLab.com, Self-managed, GitLab Dedicated - -### List Service Account Users - -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/416729) in GitLab 17.1. - -Prerequisites: - -- You must be an administrator of the self-managed instance, or have the Owner role for the group. - -Lists all service account users that are provisioned by group. - -This function takes pagination parameters `page` and `per_page` to restrict the list of users. - -```plaintext -GET /groups/:id/service_accounts -``` - -Example request: - -```shell -curl --request GET --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/345/service_accounts" -``` - -Supported attributes: - -| Attribute | Type | Required | Description | -|:-------------|:---------|:-----------|:----------------------------------------------------------------| -| `order_by` | string | no | Orders list of users by `username` or `id`. Default is `id`. | -| `sort` | string | no | Specifies sorting by `asc` or `desc`. Default is `desc`. | - -Example response: - -```json -[ - - { - "id": 57, - "username": "service_account_group_345_", - "name": "Service account user" - }, - { - "id": 58, - "username": "service_account_group_345_", - "name": "Service account user" - } -] -``` - -### Create Service Account User - -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/407775) in GitLab 16.1. -> - Ability to specify a username or name was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/144841) in GitLab 16.10. - -Creates a service account user. You can specify username and name. If you do not specify these attributes, the default name is `Service account user` and the username is automatically generated. - -This API endpoint works on top-level groups only. It does not work on subgroups. - -```plaintext -POST /groups/:id/service_accounts -``` - -```shell -curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/345/service_accounts" -``` - -Supported attributes: - -| Attribute | Type | Required | Description | -|:---------------------------|:---------------|:--------------------------|:-------------------------------------------------------------------------------| -| `name` | string | no | Name of the user | -| `username` | string | no | Username of the user | - -Example response: - -```json -{ - "id": 57, - "username": "service_account_group_345_6018816a18e515214e0c34c2b33523fc", - "name": "Service account user" -} -``` - -### Delete Service Account User - -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/416729) in GitLab 17.1. - -Deletes a service account user. You specify the ID of the service account user to be deleted. - -This API endpoint works on top-level groups only. It does not work on subgroups. - -```plaintext -DELETE /groups/:id/service_accounts/:user_id -``` - -Example request: - -```shell -curl --request DELETE --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/345/service_accounts/181" -``` - -Supported attributes: - -| Attribute | Type | Required | Description | -|:---------------------------|:---------------|:--------------------------|:-------------------------------------------------------------------------------| -| `id` | integer | yes | ID of a service account user. | -| `hard_delete` | boolean | no | If true, contributions that would usually be [moved to a Ghost User](../user/profile/account/delete_account.md#associated-records) are deleted instead, as well as groups owned solely by this service account user. | - -### Create personal access token for Service Account User - -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/406781) in GitLab 16.1. - -```plaintext -POST /groups/:id/service_accounts/:user_id/personal_access_tokens -``` - -This API endpoint works on top-level groups only. It does not work on subgroups. - -```shell -curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/35/service_accounts/71/personal_access_tokens" --data "scopes[]=api,read_user,read_repository" --data "name=service_accounts_token" -``` - -Example response: - -```json -{ - "id":6, - "name":"service_accounts_token", - "revoked":false, - "created_at":"2023-06-13T07:47:13.900Z", - "scopes":["api"], - "user_id":71, - "last_used_at":null, - "active":true, - "expires_at":"2024-06-12", - "token":"" -} -``` - -| Attribute | Type | Required | Description | -| --------- | --------------- | -------- | ----------- | -| `name` | string | yes | Name of the personal access token | -| `scopes` | array | yes | Array of scopes of the personal access token. See [personal access token scopes](../user/profile/personal_access_tokens.md#personal-access-token-scopes) for possible values. | -| `expires_at` | date | no | Personal access token expiry date. When left blank, the token follows the [standard rule of expiry for personal access tokens](../user/profile/personal_access_tokens.md#when-personal-access-tokens-expire). | - -### Rotate a personal access token for Service Account User - -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/406781) in GitLab 16.1. - -```plaintext -POST /groups/:id/service_accounts/:user_id/personal_access_tokens/:token_id/rotate -``` - -This API endpoint works on top-level groups only. It does not work on subgroups. - -```shell -curl --request POST --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/groups/35/service_accounts/71/personal_access_tokens/6/rotate" -``` - -Example response: - -```json -{ - "id":7, - "name":"service_accounts_token", - "revoked":false, - "created_at":"2023-06-13T07:54:49.962Z", - "scopes":["api"], - "user_id":71, - "last_used_at":null, - "active":true, - "expires_at":"2023-06-20", - "token":"" -} -``` - ## Markdown uploads Markdown uploads are files uploaded to a group that can be referenced in Markdown text in an epic or wiki page. diff --git a/doc/ci/cloud_deployment/ecs/deploy_to_aws_ecs.md b/doc/ci/cloud_deployment/ecs/deploy_to_aws_ecs.md index e019c108a39..d42b0362220 100644 --- a/doc/ci/cloud_deployment/ecs/deploy_to_aws_ecs.md +++ b/doc/ci/cloud_deployment/ecs/deploy_to_aws_ecs.md @@ -85,7 +85,7 @@ and [Container Registry](../../../user/packages/container_registry/index.md). Now you have a containerized application image that can be pulled from AWS. Next, you define the spec of how this application image is used in AWS. -Note that the `production_ecs` job fails because ECS Cluster is not connected yet. You'll fix this +The `production_ecs` job fails because ECS Cluster is not connected yet. You can fix this later. ### Create an ECS task definition @@ -164,7 +164,7 @@ is a daemon to create an application container based on the [ECS task definition ![An active service running.](img/service-running.png) -Note that AWS's console UI changes from time to time. If you can't find a relevant component in the +The AWS's console UI changes from time to time. If you can't find a relevant component in the instructions, select the closest one. ### View the demo application diff --git a/doc/development/architecture.md b/doc/development/architecture.md index 83a499710e2..af4c007a865 100644 --- a/doc/development/architecture.md +++ b/doc/development/architecture.md @@ -876,8 +876,8 @@ Git operations over HTTP use the stateless "smart" protocol described in the [Git documentation](https://git-scm.com/docs/http-protocol), but responsibility for handling these operations is split across several GitLab components. -Here is a sequence diagram for `git fetch`. Note that all requests pass through -NGINX as well as any other HTTP load balancers, but are not transformed in any +Here is a sequence diagram for `git fetch`. All requests pass through +NGINX and any other HTTP load balancers, but are not transformed in any way by them. All paths are presented relative to a `/namespace/project.git` URL. ```mermaid @@ -927,7 +927,7 @@ To the SSH server, all connections are authenticated as the `git` user; GitLab users are differentiated by the SSH key presented by the client. Here is a sequence diagram for `git fetch`, assuming [Fast SSH key lookup](../administration/operations/fast_ssh_key_lookup.md) -is enabled. Note that `AuthorizedKeysCommand` is an executable provided by +is enabled. `AuthorizedKeysCommand` is an executable provided by [GitLab Shell](#gitlab-shell): ```mermaid diff --git a/doc/development/code_review.md b/doc/development/code_review.md index 7b9a978f528..5c61e8716e5 100644 --- a/doc/development/code_review.md +++ b/doc/development/code_review.md @@ -663,7 +663,7 @@ WARNING: circling back with the author about that. Otherwise, if the MR only has a few commits, we'll be respecting the author's setting by not squashing them. - Go to the merge request's **Pipelines** tab, and select **Run pipeline**. Then, on the **Overview** tab, enable **Auto-merge**. - Note that: + Consider the following information: - If **[the default branch is broken](https://handbook.gitlab.com/handbook/engineering/workflow/#broken-master), do not merge the merge request** except for [very specific cases](https://handbook.gitlab.com/handbook/engineering/workflow/#criteria-for-merging-during-broken-master). diff --git a/doc/development/cookies.md b/doc/development/cookies.md new file mode 100644 index 00000000000..a8bb36fa2b3 --- /dev/null +++ b/doc/development/cookies.md @@ -0,0 +1,26 @@ +--- +stage: none +group: unassigned +info: Any user with at least the Maintainer role can merge updates to this content. For details, see https://docs.gitlab.com/ee/development/development_processes.html#development-guidelines-review. +--- + +# Cookies + +In general, there is usually a better place to store data for users than in cookies. For backend development PostgreSQL, Redis, and [session storage](session.md) are available. For frontend development, cookies may be more secure than `localStorage`, `IndexedDB` or other options. + +In general do not put sensitive information such as user IDs, potentially user-identifying information, tokens, or other secrets into cookies. See our [Secure Coding Guidelines](secure_coding_guidelines.md) for more information. + +## Cookies on Rails + +Ruby on Rails has cookie setting and retrieval [built-in to ActionController](https://guides.rubyonrails.org/action_controller_overview.html#cookies). Rails uses a cookie to track the user's session ID, which allows access to session storage. [Devise also sets a cookie](https://github.com/heartcombo/devise/blob/main/lib/devise/strategies/rememberable.rb) when users select the **Remember Me** checkbox when signing in, which allows a user to re-authenticate after closing and re-opening a browser. + +You can [set cookies with options](https://api.rubyonrails.org/v7.1.3.4/classes/ActionDispatch/Cookies.html) such as `:path` , `:expires`, `:domain` , and `:httponly` . Do not change from the defaults for these options unless it is required for the functionality you are implementing. + +WARNING: +[Cookies set by GitLab are unset by default when users log out](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/controllers/sessions_controller.rb#L104). If you set a cookie with the `:domain` option, that cookie must be unset using the same `:domain` parameter. Otherwise the browser will not actually clear the cookie, and we risk persisting potentially-sensitive data which should have been cleared. + +## Cookies in Frontend Code + +Some of our frontend code sets cookies for persisting data during a session, such as dismissing alerts or sidebar position preferences. We use the [`setCookie` and `getCookie` helpers from `common_utils`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/lib/utils/common_utils.js#L697) to apply reasonable defaults to these cookies. + +Be aware that, after 2021, browsers have started [aggressively purging cookies](https://clearcode.cc/blog/browsers-first-third-party-cookies/) and `localStorage` data set by JavaScript scripts in an effort to fight tracking scripts. If cookies seem to be unset every day or every few days, it is possible the data is getting purged, and you might want to preserve the data server-side rather than in browser-local storage. diff --git a/doc/development/database/database_debugging.md b/doc/development/database/database_debugging.md index 3adc237b1f5..35a5265b499 100644 --- a/doc/development/database/database_debugging.md +++ b/doc/development/database/database_debugging.md @@ -104,27 +104,57 @@ The new connection should be working now. ## Access the GDK database with Visual Studio Code -Use these instructions for exploring the GitLab database while developing with the GDK: +Create a database connection using the PostgreSQL extension in Visual Studio Code to access and +explore the GDK database. -1. Install or open [Visual Studio Code](https://code.visualstudio.com/download). -1. Install the [PostgreSQL VS Code Extension](https://marketplace.visualstudio.com/items?itemName=ckolkman.vscode-postgres). -1. In Visual Studio Code select **PostgreSQL Explorer** in the left toolbar. -1. In the top bar of the new window, select `+` to **Add Database Connection**, and follow the prompts to fill in the details: - 1. **Hostname**: the path to the PostgreSQL folder in your GDK directory (for example `/dev/gitlab-development-kit/postgresql`). - 1. **PostgreSQL user to authenticate as**: usually your local username, unless otherwise specified during PostgreSQL installation. - 1. **Password of the PostgreSQL user**: the password you set when installing PostgreSQL. - 1. **Port number to connect to**: `5432` (default). - 1. **Use an SSL connection?** This depends on your installation. Options are: - - **Use Secure Connection** - - **Standard Connection** (default) - 1. **Optional. The database to connect to**: `gitlabhq_development`. - 1. **The display name for the database connection**: `gitlabhq_development`. +Prerequisites: -Your database connection should now be displayed in the PostgreSQL Explorer pane and -you can explore the `gitlabhq_development` database. If you cannot connect, ensure -that GDK is running. For further instructions on how to use the PostgreSQL Explorer -Extension for Visual Studio Code, read the [usage section](https://marketplace.visualstudio.com/items?itemName=ckolkman.vscode-postgres#usage) -of the extension documentation. +- [Visual Studio (VS) Code](https://code.visualstudio.com/download). +- [PostgreSQL](https://marketplace.visualstudio.com/items?itemName=ckolkman.vscode-postgres) VS Code extension. + +To create a database connection: + +1. In the activity bar, select the **PostgreSQL Explorer** icon. +1. From the opened pane, select **+** to add a new database connection: +1. Enter the **hostname** of the database. Use the path to the PostgreSQL folder in your GDK directory. + - Example: `/dev/gitlab-development-kit/postgresql` +1. Enter a **PostgreSQL user to authenticate as**. + Use your local username unless otherwise specified during PostgreSQL installation. + To verify your PostgreSQL username: + 1. Ensure you are in the `gitlab` directory. + 1. Access the PostgreSQL database. Run `rails db`. The output should look like: + + ```shell + psql (14.9) + Type "help" for help. + + gitlabhq_development=# + ``` + + 1. In the returned PostgreSQL prompt, run `\conninfo` to display the connected user and + the port used to establish the connection. For example: + + ```shell + You are connected to database "gitlabhq_development" as user "root" on host "localhost" (address "127.0.0.1") at port "5432". + ``` + +1. When prompted to enter the **password of the PostgreSQL user**, enter the password you set or leave the field blank. + - As you are logged in to the same machine that the Postgres server is running on, a password is not required. +1. Enter**Port number to connect to**. The default port number is`5432`. +1. In the **use an SSL connection?** field, select the appropriate connection for your +installation. The options are: + - **Use Secure Connection** + - **Standard Connection** (default) +1. In the optional **database to connect to** field, enter `gitlabhq_development`. +1. In the **display name for the database connection** field, enter `gitlabhq_development`. + +Your `gitlabhq_development` database connection is now displayed in the **PostgreSQL Explorer** pane. +Use the arrows to expand and explore the contents of the GDK database. + +If you cannot connect, first ensure that GDK is running and try again. For further instructions on how +to use the PostgreSQL Explorer extension for VS Code, see +the [usage section](https://marketplace.visualstudio.com/items?itemName=ckolkman.vscode-postgres#usage) +of the extension's documentation. ## FAQ diff --git a/doc/development/distributed_tracing.md b/doc/development/distributed_tracing.md index 58039068e92..8c8ff26fbc2 100644 --- a/doc/development/distributed_tracing.md +++ b/doc/development/distributed_tracing.md @@ -199,7 +199,7 @@ This should start the process with the default listening ports. ### 2. Configure the `GITLAB_TRACING` environment variable -Once you have Jaeger running, configure the `GITLAB_TRACING` variable with the +After you have Jaeger running, configure the `GITLAB_TRACING` variable with the appropriate configuration string. If you're running everything on the same host, use the following value: @@ -220,7 +220,7 @@ This configuration string uses the Jaeger driver `opentracing://jaeger` with the | Name | Example | Description | |------|-------|-------------| -| `udp_endpoint` | `localhost:6831` | This is the default. Configures Jaeger to send trace information to the UDP listener on port `6831` using compact thrift protocol. Note that we've experienced some issues with the [Jaeger Client for Ruby](https://github.com/salemove/jaeger-client-ruby) when using this protocol. | +| `udp_endpoint` | `localhost:6831` | This is the default. Configures Jaeger to send trace information to the UDP listener on port `6831` using compact thrift protocol. We've experienced some issues with the [Jaeger Client for Ruby](https://github.com/salemove/jaeger-client-ruby) when using this protocol. | | `sampler` | `probabilistic` | Configures Jaeger to use a probabilistic random sampler. The rate of samples is configured by the `sampler_param` value. | | `sampler_param` | `0.01` | Use a ratio of `0.01` to configure the `probabilistic` sampler to randomly sample _1%_ of traces. | | `service_name` | `api` | Override the service name used by the Jaeger backend. This parameter takes precedence over the application-supplied value. | diff --git a/doc/development/documentation/graphql_styleguide.md b/doc/development/documentation/graphql_styleguide.md index 264ba19226f..192810b0a6b 100644 --- a/doc/development/documentation/graphql_styleguide.md +++ b/doc/development/documentation/graphql_styleguide.md @@ -66,7 +66,7 @@ Set up the section with the following: ``` - Include a screenshot of the result in the GraphiQL explorer. Follow the naming - convention described in the [Save the image](styleguide/index.md#save-the-image) section of the Documentation style guide. + convention described in [Image requirements](styleguide/index.md#image-requirements). - Follow up with an example of what you can do with the output. Make sure the example is something that readers can do on their own deployments. - Include a link to the [GraphQL API resources](../../api/graphql/reference/index.md). diff --git a/doc/development/documentation/styleguide/index.md b/doc/development/documentation/styleguide/index.md index 9dd347f2156..3a61eb5360b 100644 --- a/doc/development/documentation/styleguide/index.md +++ b/doc/development/documentation/styleguide/index.md @@ -1189,12 +1189,14 @@ If you need to emphasize an area in a screenshot, use an arrow. ![callout example](img/callouts.png) -#### Save the image +#### Image requirements -- Resize any wide or tall screenshots if needed, but make sure the screenshot is - still clear after being resized and compressed. -- All images **must** be [compressed](#compress-images) to 100KB or less. - In many cases, 25-50KB or less is often possible without reducing image quality. +- Resize any wide or tall screenshots. + - Width should be 1000 pixels or less. + - Height should be 500 pixels or less. + - Make sure the screenshot is still clear after being resized and compressed. +- All images **must** be [compressed](#compress-images) to 100 KB or less. + In many cases, 25-50 KB or less is often possible without reducing image quality. - Save the image with a lowercase filename that's descriptive of the feature or concept in the image: - If the image is of the GitLab interface, append the GitLab version to the filename, @@ -1207,7 +1209,8 @@ If you need to emphasize an area in a screenshot, use an arrow. the `.md` document that you're working on is located. - Consider using PNG images instead of JPEG. - Compress GIFs with or similar tool. -- See also how to link and embed [videos](#videos) to illustrate the documentation. + +See also how to link and embed [videos](#videos) to illustrate the documentation. #### Compress images diff --git a/doc/development/ee_features.md b/doc/development/ee_features.md index bb5ac601936..399121b1cf9 100644 --- a/doc/development/ee_features.md +++ b/doc/development/ee_features.md @@ -856,8 +856,7 @@ module EE end ``` -Note that due to namespace differences, we need to use the full qualifier for some -constants. +We need to use the full qualifier for some constants due to namespace differences. #### EE parameters @@ -1005,7 +1004,7 @@ end API::MergeRequests.prepend_mod_with('API::MergeRequests') ``` -Note that `update_merge_request_ee` doesn't do anything in CE, but +`update_merge_request_ee` doesn't do anything in CE, but then we could override it in EE: ```ruby @@ -1188,7 +1187,7 @@ Instead place EE specs in the `ee/spec` folder. Use `FactoryBot.modify` to extend factories already defined in CE. -Note that you cannot define new factories (even nested ones) inside the `FactoryBot.modify` block. You can do so in a +You cannot define new factories (even nested ones) inside the `FactoryBot.modify` block. You can do so in a separate `FactoryBot.define` block as shown in the example below: ```ruby diff --git a/doc/development/fips_compliance.md b/doc/development/fips_compliance.md index 4dac7742477..0944b1d2cde 100644 --- a/doc/development/fips_compliance.md +++ b/doc/development/fips_compliance.md @@ -285,7 +285,7 @@ Registration is required. After the virtual machine is set up, you can follow the [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit) installation instructions, including the [advanced instructions for RHEL](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/advanced.md#red-hat-enterprise-linux). -Note that `asdf` is not used for dependency management because it's essential to +The `asdf` tool is not used for dependency management because it's essential to use the RedHat-provided Go compiler and other system dependencies. ### Enable FIPS mode @@ -465,7 +465,7 @@ The Cloud Native GitLab CI pipeline generates images using several base images: UBI images ship with the same OpenSSL package as those used by RHEL. This makes it possible to build FIPS-compliant binaries without -needing RHEL. Note that RHEL 8.2 ships a [FIPS-validated OpenSSL](https://access.redhat.com/articles/compliance_activities_and_gov_standards), but 8.5 is in +needing RHEL. RHEL 8.2 ships a [FIPS-validated OpenSSL](https://access.redhat.com/articles/compliance_activities_and_gov_standards), but 8.5 is in review for FIPS validation. [This merge request](https://gitlab.com/gitlab-org/build/CNG/-/merge_requests/981) diff --git a/doc/development/gems.md b/doc/development/gems.md index 825abf01029..247c757b3e0 100644 --- a/doc/development/gems.md +++ b/doc/development/gems.md @@ -152,8 +152,8 @@ You can see example adding a new gem: [!121676](https://gitlab.com/gitlab-org/gi ### Specifying dependencies for the Gem -It is important to note that while the gem has its own `Gemfile`, in the -actual application the top-level `Gemfile` for the monolith GitLab will be +While the gem has its own `Gemfile`, in the +actual application the top-level `Gemfile` for the monolith GitLab is used instead of the individual `Gemfile` sitting in the directory of the gem. This means we should be aware that the `Gemfile` for the gem should not use @@ -167,7 +167,7 @@ all gems we develop should also be tested against Rack 2, optionally also with Rack 3 if a separate `Gemfile` is used in CI. See an [example here](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/140463). -Note that this does not limit to just Rack, but any dependencies. +This does not limit to just Rack, but any dependencies. ### Examples of Gem extractions diff --git a/doc/development/gitaly.md b/doc/development/gitaly.md index 3d7ce2c7ae6..ef4eb262eb8 100644 --- a/doc/development/gitaly.md +++ b/doc/development/gitaly.md @@ -144,7 +144,7 @@ tests. Otherwise, Gitaly fails to boot. If you make changes to your local Gitaly in between test runs you need to manually run `make` again. -Note that CI tests do not use your locally modified version of +CI tests do not use your locally modified version of Gitaly. To use a custom Gitaly version in CI, you must update `GITALY_SERVER_VERSION` as described at the beginning of this section. diff --git a/doc/development/import_project.md b/doc/development/import_project.md index fba8c5b8dda..5addf42691d 100644 --- a/doc/development/import_project.md +++ b/doc/development/import_project.md @@ -30,7 +30,7 @@ This method ignores all the errors silently (including the ones related to `GITA A convenient script, [`bin/import-project`](https://gitlab.com/gitlab-org/quality/performance/blob/master/bin/import-project), is provided with [performance](https://gitlab.com/gitlab-org/quality/performance) project to import the Project tarball into a GitLab environment via API from the terminal. -Note that to use the script, it requires some preparation if you haven't done so already: +It requires some preparation to use the script if you haven't done so already: 1. First, set up [`Ruby`](https://www.ruby-lang.org/en/documentation/installation/) and [`Ruby Bundler`](https://bundler.io) if they aren't already available on the machine. 1. Next, install the required Ruby Gems via Bundler with `bundle install`. diff --git a/doc/development/logging.md b/doc/development/logging.md index 983019b2ccd..ad3990c3302 100644 --- a/doc/development/logging.md +++ b/doc/development/logging.md @@ -41,7 +41,7 @@ These logs suffer from a number of problems: forwarders, such as Logstash or Fluentd. This also makes them hard to search. -Note that currently on GitLab.com, any messages in `production.log` aren't +Currently on GitLab.com, any messages in `production.log` aren't indexed by Elasticsearch due to the sheer volume and noise. They do end up in Google Stackdriver, but it is still harder to search for logs there. See the [GitLab.com logging documentation](https://gitlab.com/gitlab-com/runbooks/-/tree/master/docs/logging) @@ -87,7 +87,7 @@ importer progresses. Here's what to do: end ``` - Note that by default, `Gitlab::JsonLogger` will include application context metadata in the log entry. If your + By default, `Gitlab::JsonLogger` will include application context metadata in the log entry. If your logger is expected to be called outside of an application request (for example, in a `rake` task) or by low-level code that may be involved in building the application context (for example, database connection code), you should call the class method `exclude_context!` for your logger class, like so: @@ -119,8 +119,8 @@ importer progresses. Here's what to do: end ``` - Note that it's useful to memoize this because creating a new logger - each time you log opens a file, adding unnecessary overhead. + It is useful to memoize the logger because creating a new logger + each time you log opens a file adds unnecessary overhead. 1. Now insert log messages into your code. When adding logs, make sure to include all the context as key-value pairs: diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md index 1256b559716..c8351b341e9 100644 --- a/doc/development/migration_style_guide.md +++ b/doc/development/migration_style_guide.md @@ -537,7 +537,7 @@ end #### Changing default value for a column -Note that changing column defaults can cause application downtime if a multi-release process is not followed. +Changing column defaults can cause application downtime if a multi-release process is not followed. See [avoiding downtime in migrations for changing column defaults](database/avoiding_downtime_in_migrations.md#changing-column-defaults) for details. ```ruby @@ -749,7 +749,7 @@ ALTER TABLE my_notes ADD COLUMN title text; The lock retry helper would repeatedly try the same transaction at different time intervals until it succeeded. -Note that `SET LOCAL` scopes the parameter (`lock_timeout`) change to +`SET LOCAL` scopes the parameter (`lock_timeout`) change to the transaction. ## Removing indexes @@ -779,7 +779,7 @@ You can verify that the index is not being used with [Grafana](https://dashboard sum by (type)(rate(pg_stat_user_indexes_idx_scan{env="gprd", indexrelname="INSERT INDEX NAME HERE"}[30d])) ``` -Note that it is not necessary to check if the index exists prior to +It is not necessary to check if the index exists prior to removing it, however it is required to specify the name of the index that is being removed. This can be done either by passing the name as an option to the appropriate form of `remove_index` or `remove_concurrent_index`, @@ -1447,9 +1447,9 @@ class AddAndSeedMyColumn < Gitlab::Database::Migration[2.1] end ``` -The underlying table is modified and then accessed via ActiveRecord. +The underlying table is modified and then accessed by using ActiveRecord. -Note that this also needs to be used if the table is modified in a previous, different migration, +This also needs to be used if the table is modified in a previous, different migration, if both migrations are run in the same `db:migrate` process. This results in the following. Note the inclusion of `my_column`: @@ -1493,7 +1493,7 @@ different features of GitLab with different usage patterns, thus making assumpti on GitLab.com not enough. To identify a high-traffic table for GitLab.com the following measures are considered. -Note that the metrics linked here are GitLab-internal only: +The metrics linked here are GitLab-internal only: - [Read operations](https://dashboards.gitlab.net/explore?schemaVersion=1&panes=%7B%22m95%22:%7B%22datasource%22:%22e58c2f51-20f8-4f4b-ad48-2968782ca7d6%22,%22queries%22:%5B%7B%22refId%22:%22A%22,%22expr%22:%22topk%28500,%20sum%20by%20%28relname%29%20%28rate%28pg_stat_user_tables_seq_tup_read%7Benvironment%3D%5C%22gprd%5C%22%7D%5B12h%5D%29%20%2B%20rate%28pg_stat_user_tables_idx_scan%7Benvironment%3D%5C%22gprd%5C%22%7D%5B12h%5D%29%20%2B%20rate%28pg_stat_user_tables_idx_tup_fetch%7Benvironment%3D%5C%22gprd%5C%22%7D%5B12h%5D%29%29%29%22,%22range%22:true,%22instant%22:true,%22datasource%22:%7B%22type%22:%22prometheus%22,%22uid%22:%22e58c2f51-20f8-4f4b-ad48-2968782ca7d6%22%7D,%22editorMode%22:%22code%22,%22legendFormat%22:%22__auto%22%7D%5D,%22range%22:%7B%22from%22:%22now-12h%22,%22to%22:%22now%22%7D%7D%7D&orgId=1) - [Number of records](https://dashboards.gitlab.net/explore?schemaVersion=1&panes=%7B%22m95%22:%7B%22datasource%22:%22e58c2f51-20f8-4f4b-ad48-2968782ca7d6%22,%22queries%22:%5B%7B%22refId%22:%22A%22,%22expr%22:%22topk%28500,%20max%20by%20%28relname%29%20%28pg_stat_user_tables_n_live_tup%7Benvironment%3D%5C%22gprd%5C%22%7D%29%29%22,%22range%22:true,%22instant%22:true,%22datasource%22:%7B%22type%22:%22prometheus%22,%22uid%22:%22e58c2f51-20f8-4f4b-ad48-2968782ca7d6%22%7D,%22editorMode%22:%22code%22,%22legendFormat%22:%22__auto%22%7D%5D,%22range%22:%7B%22from%22:%22now-6h%22,%22to%22:%22now%22%7D%7D%7D&orgId=1) diff --git a/doc/integration/kerberos_troubleshooting.md b/doc/integration/kerberos_troubleshooting.md index 569c6c34491..18c3e2d7246 100644 --- a/doc/integration/kerberos_troubleshooting.md +++ b/doc/integration/kerberos_troubleshooting.md @@ -121,6 +121,17 @@ set the `http.emptyAuth` Git option to `true` to fix this: git config --global http.emptyAuth true ``` +## Git cloning with Kerberos over proxied HTTPS + +You must comment the following if: + +- You see `http://` URLs in the **Clone with KRB5 Git Cloning** options, when `https://` URLs are expected. +- HTTPS is not terminated at your GitLab instance, but is instead proxied by your load balancer or local traffic manager. + +```shell +# gitlab_rails['kerberos_https'] = false +``` + See also: [Git v2.11 release notes](https://github.com/git/git/blob/master/Documentation/RelNotes/2.11.0.txt#L482-L486) ## Helpful links diff --git a/doc/security/identity_verification.md b/doc/security/identity_verification.md index 5c3f9114632..fc832de0b2c 100644 --- a/doc/security/identity_verification.md +++ b/doc/security/identity_verification.md @@ -11,6 +11,8 @@ DETAILS: **Offering:** GitLab.com > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95722) in GitLab 15.4 [with a flag](../administration/feature_flags.md) named `identity_verification`. Disabled by default. +> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/371389) in GitLab 16.0. +> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/371389) in GitLab 16.11. Feature flag `identity_verification` removed. Identity verification provides multiple layers of GitLab account security. Depending on your [risk score](../integration/arkose.md), you might be required to perform up to @@ -25,7 +27,7 @@ Users created after signing in with [SAML SSO for GitLab.com groups](../user/gro ## Email verification To register an account, you must provide a valid email address. -See [Account email verification](email_verification.md). +See [Make new users confirm email](user_email_confirmation.md). ## Phone number verification diff --git a/doc/subscriptions/choosing_subscription.md b/doc/subscriptions/choosing_subscription.md index 63c2b9a587f..843dff9bce1 100644 --- a/doc/subscriptions/choosing_subscription.md +++ b/doc/subscriptions/choosing_subscription.md @@ -13,15 +13,15 @@ To choose the right GitLab subscription, select an offering and a tier. Choose which GitLab subscription suits your needs: -- [GitLab SaaS](gitlab_com/index.md): The GitLab software-as-a-service offering. - You don't need to install anything to use GitLab SaaS, you only need to +- [GitLab.com](gitlab_com/index.md): The GitLab software-as-a-service offering. + You don't need to install anything to use GitLab.com, you only need to [sign up](https://gitlab.com/users/sign_up) and start using GitLab straight away. - [GitLab Dedicated](gitlab_dedicated/index.md): A single-tenant SaaS service for highly regulated and large enterprises. - [GitLab self-managed](self_managed/index.md): Install, administer, and maintain your own GitLab instance. On a GitLab self-managed instance, a GitLab subscription provides the same set of -features for _all_ users. On GitLab SaaS, you can apply a subscription to a group +features for _all_ users. On GitLab.com, you can apply a subscription to a top-level group namespace. You cannot apply a subscription to a personal namespace. NOTE: @@ -33,8 +33,7 @@ A new subscription must be purchased and applied as needed. Pricing is [tier-based](https://about.gitlab.com/pricing/), allowing you to choose the features that fit your budget. -For more details, see -[a comparison of self-managed features available in each tier](https://about.gitlab.com/pricing/feature-comparison/). +For more details, see [a comparison of features available in each tier](https://about.gitlab.com/pricing/feature-comparison/). ## Find your subscription diff --git a/doc/subscriptions/community_programs.md b/doc/subscriptions/community_programs.md index c4a29650566..007b117a587 100644 --- a/doc/subscriptions/community_programs.md +++ b/doc/subscriptions/community_programs.md @@ -1,8 +1,8 @@ --- -stage: Fulfillment -group: Subscription Management +stage: none +group: unassigned description: Education, Open Source, Startups. -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments +info: For help with this Community Programs page, see https://handbook.gitlab.com/handbook/marketing/developer-relations/community-programs/ --- # Community programs diff --git a/doc/user/discussions/index.md b/doc/user/discussions/index.md index faebafa62d0..628bc0f5ff2 100644 --- a/doc/user/discussions/index.md +++ b/doc/user/discussions/index.md @@ -17,7 +17,7 @@ DETAILS: > - Paginated merge request discussions [generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/370075) in GitLab 15.8. Feature flag `paginated_mr_discussions` removed. GitLab encourages communication through comments, threads, and -[Code Suggestions](../project/merge_requests/reviews/suggestions.md). +[suggesting changes for code](../project/merge_requests/reviews/suggestions.md). Comments support [Markdown](../markdown.md) and [quick actions](../project/quick_actions.md). Two types of comments are available: diff --git a/doc/user/profile/personal_access_tokens.md b/doc/user/profile/personal_access_tokens.md index e0bb20114f4..9f58235b697 100644 --- a/doc/user/profile/personal_access_tokens.md +++ b/doc/user/profile/personal_access_tokens.md @@ -245,7 +245,7 @@ You can subscribe to an iCalendar endpoint which contains events at the expiry d ### Create a service account personal access token with no expiry date -You can [create a personal access token for a service account](../../api/groups.md#create-personal-access-token-for-service-account-user) with no expiry date. These personal access tokens never expire, unlike non-service account personal access tokens. +You can [create a personal access token for a service account](../../api/group_service_accounts.md#create-a-personal-access-token-for-a-service-account-user) with no expiry date. These personal access tokens never expire, unlike non-service account personal access tokens. NOTE: Allowing personal access tokens for service accounts to be created with no expiry date only affects tokens created after you change this setting. It does not affect existing tokens. diff --git a/doc/user/profile/service_accounts.md b/doc/user/profile/service_accounts.md index aca7d1f0443..2c7ef2fa62f 100644 --- a/doc/user/profile/service_accounts.md +++ b/doc/user/profile/service_accounts.md @@ -54,13 +54,13 @@ Prerequisites: - You must have the Owner role in a top-level group. -1. [Create a service account](../../api/groups.md#create-service-account-user). +1. [Create a service account](../../api/group_service_accounts.md#create-a-service-account-user). This service account is associated only with your top-level group. -1. [List all service account users](../../api/groups.md#list-service-account-users). +1. [List all service account users](../../api/group_service_accounts.md#list-service-account-users). -1. [Create a personal access token](../../api/groups.md#create-personal-access-token-for-service-account-user) +1. [Create a personal access token](../../api/group_service_accounts.md#create-a-personal-access-token-for-a-service-account-user) for the service account user. You define the scopes for the service account by [setting the scopes for the personal access token](personal_access_tokens.md#personal-access-token-scopes). @@ -144,7 +144,7 @@ Prerequisites: - For GitLab.com, you must have the Owner role in a top-level group. - For self-managed GitLab, you must be an administrator for your self-managed instance. -Use the groups API to [rotate the personal access token](../../api/groups.md#rotate-a-personal-access-token-for-service-account-user) for a service account user. +Use the groups API to [rotate the personal access token](../../api/group_service_accounts.md#rotate-a-personal-access-token-for-a-service-account-user) for a service account user. ### Revoke a personal access token @@ -165,7 +165,7 @@ Prerequisites: - You must have the Owner role in a top-level group. -To delete a service account, [use the groups API to delete the service account user](../../api/groups.md#delete-service-account-user). +To delete a service account, [use the service accounts API to delete the service account user](../../api/group_service_accounts.md#delete-a-service-account-user). #### Self-managed GitLab diff --git a/doc/user/project/code_intelligence.md b/doc/user/project/code_intelligence.md index 4bc3be88907..7b9eb5dcae5 100644 --- a/doc/user/project/code_intelligence.md +++ b/doc/user/project/code_intelligence.md @@ -22,25 +22,109 @@ Code intelligence is built into GitLab and powered by [LSIF](https://lsif.dev/) intelligence data. GitLab processes one LSIF file per project, and Code intelligence does not support different LSIF files per branch. -Follow [epic 4212](https://gitlab.com/groups/gitlab-org/-/epics/4212) -for progress on upcoming code intelligence enhancements. +[SCIP](https://github.com/sourcegraph/scip/) is the next evolution of tooling +for indexing source code. You can use it to power code navigation features, +such as: -NOTE: -You can automate this feature in your applications by using [Auto DevOps](../../topics/autodevops/index.md). +- Go to definition +- Find references + +GitLab does not natively support SCIP for code intelligence. However, you can use the +[SCIP CLI](https://github.com/sourcegraph/scip/blob/main/docs/CLI.md) to convert +indexes generated with SCIP tooling into a LSIF-compatible file. For discussions on native +SCIP support, see [issue 412981](https://gitlab.com/gitlab-org/gitlab/-/issues/412981). + +For progress on upcoming code intelligence enhancements, see +[epic 4212](https://gitlab.com/groups/gitlab-org/-/epics/4212). ## Configure code intelligence Prerequisites: -- You've checked the LSIF documentation to confirm an - [LSIF indexer](https://lsif.dev/#implementations-server) exists for your project's languages. +- You've checked to ensure there is a compatible indexer for your project's languages: + - [LSIF indexers](https://lsif.dev/#implementations-server) + - [SCIP indexers](https://github.com/sourcegraph/scip/#tools-using-scip) -To enable code intelligence for a project: +To see how your language is best supported, review the +[indexers recommended by Sourcegraph](https://sourcegraph.com/docs/code-search/code-navigation/writing_an_indexer#sourcegraph-recommended-indexers). -1. Add a GitLab CI/CD job to your project's `.gitlab-ci.yml`. This job generates the LSIF artifact: +### With the CI/CD component + +GitLab provides a [CI/CD component](../../ci/components/index.md) to configure code intelligence +in your `.gitlab-ci.yml` file. The component supports these languages: + +- Go version 1.21 or later. +- TypeScript or JavaScript. (To contribute more languages to the component, open a merge request in the + [Code intelligence component project](https://gitlab.com/components/code-intelligence).) + +1. Add a GitLab CI/CD component to your project's `.gitlab-ci.yml`. For example, this job generates + the LSIF artifact for `golang`: + + ```yaml + - component: ${CI_SERVER_FQDN}/components/code-intelligence/golang-code-intel@v0.0.2 + inputs: + golang_version: ${GO_VERSION} + ``` + +1. For configuration instructions for the [code intelligence component](https://gitlab.com/components/code-intelligence), + check the `README` for each supported language. +1. For more configuration details, see [Use a component](../../ci/components/index.md#use-a-component). + +### Add CI/CD jobs for code intelligence + +To enable code intelligence for a project, add GitLab CI/CD jobs to your project's `.gitlab-ci.yml`. + +::Tabs + +:::TabTitle With a SCIP indexer + +1. Add two jobs to your `.gitlab-ci.yml` configuration. The first job (`code_navigation_generate`) + generates the SCIP index. The second job (`code_navigation_convert`) converts the SCIP index to LSIF for use in GitLab: + + ```yaml + code_navigation_generate: + rules: + - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH # the job only needs to run against the default branch + image: node:latest + stage: test + allow_failure: true # recommended + script: + - npm install -g @sourcegraph/scip-typescript + - npm install + - scip-typescript index + artifacts: + paths: + - index.scip + + code_navigation_convert: + rules: + - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH # the job only needs to run against the default branch + image: golang + stage: test + allow_failure: true # recommended + needs: ["code_navigation_generate"] + script: + - git clone --branch v0.4.0 --depth 1 https://github.com/sourcegraph/scip.git + - cd scip + - go build ./cmd/scip + - chmod +x scip + - ./scip convert --from ../index.scip --to ../dump.lsif + artifacts: + reports: + lsif: dump.lsif + ``` + +1. Depending on your CI/CD configuration, you might need to run the job manually, + or wait for it to run as part of an existing pipeline. + +:::TabTitle With a LSIF indexer + +1. Add a job (`code_navigation`) to your `.gitlab-ci.yml` configuration to generate the index: ```yaml code_navigation: + rules: + - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH # the job only needs to run against the default branch image: sourcegraph/lsif-go:v1 allow_failure: true # recommended script: @@ -53,10 +137,13 @@ To enable code intelligence for a project: 1. Depending on your CI/CD configuration, you might need to run the job manually, or wait for it to run as part of an existing pipeline. -This file is limited to 100 MB by the +::EndTabs + +NOTE: +GitLab limits the artifact produced by the code generation jobs to 100 MB by the [(`ci_max_artifact_size_lsif`)](../../administration/instance_limits.md#maximum-file-size-per-type-of-artifact) artifact application limit. On self-managed installations, an instance administrator -can configure this value. +can change this value. ## View code intelligence results diff --git a/lib/gitlab/utils/email.rb b/lib/gitlab/utils/email.rb index 47fb30d66f8..3679b5c444b 100644 --- a/lib/gitlab/utils/email.rb +++ b/lib/gitlab/utils/email.rb @@ -30,16 +30,21 @@ module Gitlab end end - def normalize_email(email = '') - return unless EMAIL_REGEXP.match(email) + def normalize_email(email) + return email unless email.is_a?(String) + return email unless Devise.email_regexp.match?(email.strip) - portions = email.split('@') - username = portions.shift - rest = portions.join + portions = email.downcase.strip.split('@') + mailbox = portions.shift + domain = portions.join - no_dots = username.tr('.', '') - before_plus = no_dots.split('+')[0] - "#{before_plus}@#{rest}" + mailbox_root = mailbox.split('+')[0] + + # Gmail addresses strip the "." from their emails. + # For example, user.name@gmail.com is the same as username@gmail.com + mailbox_root = mailbox_root.tr('.', '') if domain == 'gmail.com' + + [mailbox_root, domain].join('@') end class Masker diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 46bbfe8bdad..214625e69fc 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -48073,6 +48073,9 @@ msgstr "" msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request" msgstr "" +msgid "SecurityDescription|The linked group refers to the groups that are linked to security policy projects. Security policy projects store your organization's security policies. They are identified when policies are created, or when a project is linked as a security policy project. %{linkStart}Learn more%{linkEnd}." +msgstr "" + msgid "SecurityOrchestration| and " msgstr "" @@ -48204,7 +48207,7 @@ msgstr "" msgid "SecurityOrchestration|Any merge request" msgstr "" -msgid "SecurityOrchestration|Apply this policy to %{projectScopeType} %{exceptionType} %{projectSelector}" +msgid "SecurityOrchestration|Apply this policy to %{projectScopeType} %{projectSelector}" msgstr "" msgid "SecurityOrchestration|Apply this policy to %{projectScopeType}named %{frameworkSelector}" @@ -48363,9 +48366,15 @@ msgstr "" msgid "SecurityOrchestration|Failed to load group projects" msgstr "" +msgid "SecurityOrchestration|Failed to load groups" +msgstr "" + msgid "SecurityOrchestration|Failed to load images." msgstr "" +msgid "SecurityOrchestration|Failed to load projects" +msgstr "" + msgid "SecurityOrchestration|Fallback behavior in case of policy failure" msgstr "" @@ -48809,6 +48818,9 @@ msgstr "" msgid "SecurityOrchestration|What does an example message look like?" msgstr "" +msgid "SecurityOrchestration|What is linked group?" +msgstr "" + msgid "SecurityOrchestration|When %{scanners} %{vulnerabilitiesAllowed} %{vulnerability} in an open merge request %{targeting}%{branches}%{branchExceptionsString}%{criteriaApply}" msgstr "" @@ -48848,6 +48860,9 @@ msgstr "" msgid "SecurityOrchestration|You must select one or more compliance frameworks to which this policy should apply." msgstr "" +msgid "SecurityOrchestration|You must select one or more groups from this policy." +msgstr "" + msgid "SecurityOrchestration|You must select one or more projects to be excluded from this policy." msgstr "" @@ -48875,7 +48890,10 @@ msgstr "" msgid "SecurityOrchestration|all namespaces" msgstr "" -msgid "SecurityOrchestration|all subgroups/projects in this group" +msgid "SecurityOrchestration|all projects in the linked groups" +msgstr "" + +msgid "SecurityOrchestration|all projects in this group" msgstr "" msgid "SecurityOrchestration|any" @@ -48917,6 +48935,9 @@ msgstr "" msgid "SecurityOrchestration|except branches" msgstr "" +msgid "SecurityOrchestration|except groups" +msgstr "" + msgid "SecurityOrchestration|except projects" msgstr "" diff --git a/scripts/review_apps/automated_cleanup.rb b/scripts/review_apps/automated_cleanup.rb index 182b35c05e8..9b4953b86fa 100755 --- a/scripts/review_apps/automated_cleanup.rb +++ b/scripts/review_apps/automated_cleanup.rb @@ -79,7 +79,7 @@ module ReviewApps def perform_gitlab_environment_cleanup!(env_prefix:, days_for_delete:) puts "Dry-run mode." if dry_run - puts "Checking for GitLab #{env_prefix} environments without any deployments in them, or deployed more than #{days_for_delete} days ago..." + puts "Checking for GitLab #{env_prefix} environments deployed more than #{days_for_delete} days ago..." delete_threshold = threshold_time(days: days_for_delete) @@ -87,9 +87,7 @@ module ReviewApps next unless environment.name.start_with?(env_prefix) # TODO: Find a way to reset those, so that we can properly delete them. next if environment.state == 'stopping' # We cannot delete environments in stopping state - - deployments = gitlab.deployments(project_path, environment: environment.name, order_by: :created_at, sort: :desc) - next if deployments.count > 0 && Time.parse(deployments.first.created_at) > delete_threshold + next if Time.parse(environment.created_at) > delete_threshold stop_environment(environment) delete_environment(environment) @@ -217,7 +215,7 @@ if $PROGRAM_NAME == __FILE__ puts timed('Review Apps Environments cleanup') do - automated_cleanup.perform_gitlab_environment_cleanup!(env_prefix: 'review/', days_for_delete: 7) + automated_cleanup.perform_gitlab_environment_cleanup!(env_prefix: 'review/', days_for_delete: 14) end timed('Docs Review Apps environments cleanup') do diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb index 51464efe239..1bd6c965ba9 100644 --- a/spec/db/schema_spec.rb +++ b/spec/db/schema_spec.rb @@ -171,7 +171,7 @@ RSpec.describe 'Database schema', feature_category: :database do vulnerability_identifiers: %w[external_id], vulnerability_occurrence_identifiers: %w[project_id], vulnerability_scanners: %w[external_id], - security_scans: %w[pipeline_id], # foreign key is not added as ci_pipeline table will be moved into different db soon + security_scans: %w[pipeline_id project_id], # foreign key is not added as ci_pipeline table will be moved into different db soon dependency_list_exports: %w[pipeline_id], # foreign key is not added as ci_pipeline table is in different db vulnerability_reads: %w[cluster_agent_id], # See: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/87584 diff --git a/spec/frontend/merge_request_tabs_spec.js b/spec/frontend/merge_request_tabs_spec.js index 5eac583d000..6efedf14521 100644 --- a/spec/frontend/merge_request_tabs_spec.js +++ b/spec/frontend/merge_request_tabs_spec.js @@ -232,6 +232,24 @@ describe('MergeRequestTabs', () => { expect(testContext.subject('commits')).toBe('/foo/bar/-/merge_requests/1/commits'); }); + it('changes from notes ending with a trailing slash', () => { + setLocation({ + pathname: '/foo/bar/-/merge_requests/1/', + }); + + expect(testContext.subject('diffs')).toBe('/foo/bar/-/merge_requests/1/diffs'); + expect(testContext.subject('commits')).toBe('/foo/bar/-/merge_requests/1/commits'); + }); + + it('changes from diffs ending with a trailing slash', () => { + setLocation({ + pathname: '/foo/bar/-/merge_requests/1/diffs/', + }); + + expect(testContext.subject('show')).toBe('/foo/bar/-/merge_requests/1'); + expect(testContext.subject('commits')).toBe('/foo/bar/-/merge_requests/1/commits'); + }); + it('includes search parameters and hash string', () => { setLocation({ pathname: '/foo/bar/-/merge_requests/1/diffs', diff --git a/spec/lib/gitlab/utils/email_spec.rb b/spec/lib/gitlab/utils/email_spec.rb index cb4c7ad630a..9d939a49da6 100644 --- a/spec/lib/gitlab/utils/email_spec.rb +++ b/spec/lib/gitlab/utils/email_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'fast_spec_helper' +require 'spec_helper' require 'rspec-parameterized' RSpec.describe Gitlab::Utils::Email, feature_category: :service_desk do @@ -74,14 +74,18 @@ RSpec.describe Gitlab::Utils::Email, feature_category: :service_desk do using RSpec::Parameterized::TableSyntax where(:raw_email, :expected_result) do - nil | nil - 'notanemail@' | nil - '@notanemail.com' | nil - 'notanemail' | nil - 'user@includeddomain.com' | 'user@includeddomain.com' - 'u.s.e.r@includeddomain.com' | 'user@includeddomain.com' - 'user+123@includeddomain.com' | 'user@includeddomain.com' - 'us.er+123@includeddomain.com' | 'user@includeddomain.com' + nil | nil + 'notanemail@' | 'notanemail@' + '@notanemail.com' | '@notanemail.com' + 'NotAnEmail' | 'NotAnEmail' + 'USER@example.com' | 'user@example.com' + 'u.s.e.r@example.com' | 'u.s.e.r@example.com' + 'user+123@example.com' | 'user@example.com' + 'us.er+123@example.com' | 'us.er@example.com' + 'u.s.e.r@gmail.com' | 'user@gmail.com' + 'user+123@gmail.com' | 'user@gmail.com' + 'us.er+123@gmail.com' | 'user@gmail.com' + ' us.er+123@gmail.com ' | 'user@gmail.com' end with_them do diff --git a/spec/models/email_spec.rb b/spec/models/email_spec.rb index b73e525a324..a0ffc1556d0 100644 --- a/spec/models/email_spec.rb +++ b/spec/models/email_spec.rb @@ -204,4 +204,37 @@ RSpec.describe Email do it_behaves_like 'confirms the email on force_confirm' end end + + describe '#before_save' do + let_it_be(:user) { create(:user) } + + context 'when the feature flag is enabled' do + it 'sets the detumbled_email attribute' do + email = described_class.new(user: user, email: 'test.user+gitlab@example.com') + + expect { email.save! }.to change { email.detumbled_email }.from(nil).to('test.user@example.com') + end + end + + context 'when the feature flag is disabled' do + before do + stub_feature_flags(store_detumbled_email: false) + end + + it 'does not set the detumbled_email attribute' do + email = described_class.new(user: user, email: 'test.user+gitlab@example.com') + + expect { email.save! }.not_to change { email.detumbled_email } + end + end + + context 'when the email attribute has not changed' do + it 'does not execute the before_action' do + email = create(:email) + + expect(email).not_to receive(:detumble_email!) + email.update!(confirmed_at: Time.now.utc) + end + end + end end diff --git a/spec/scripts/review_apps/automated_cleanup_spec.rb b/spec/scripts/review_apps/automated_cleanup_spec.rb index f3b74a9077a..8c4bf37c92c 100644 --- a/spec/scripts/review_apps/automated_cleanup_spec.rb +++ b/spec/scripts/review_apps/automated_cleanup_spec.rb @@ -148,8 +148,8 @@ RSpec.describe ReviewApps::AutomatedCleanup, feature_category: :tooling do describe '#perform_gitlab_environment_cleanup!' do let(:env_prefix) { 'test-prefix/' } - let(:days_for_delete) { 2 } - let(:deployment_created_at) { three_days_ago.to_s } + let(:days_for_delete) { 2 } + let(:environment_created_at) { two_days_ago.to_s } let(:env_name) { "#{env_prefix}an-env-name" } let(:env_state) { 'available' } # rubocop:disable RSpec/VerifiedDoubles -- Internal API resource @@ -159,11 +159,7 @@ RSpec.describe ReviewApps::AutomatedCleanup, feature_category: :tooling do name: env_name, slug: env_name, state: env_state, - created_at: one_day_ago.to_s)] - end - - let(:deployments) do - [double('GitLab Deployment', created_at: deployment_created_at)] + created_at: environment_created_at)] end subject do @@ -175,7 +171,6 @@ RSpec.describe ReviewApps::AutomatedCleanup, feature_category: :tooling do before do allow(gitlab_client).to yield_environments(:environments, environments) - allow(gitlab_client).to receive(:deployments).and_return(deployments) # Silence outputs to stdout allow(instance).to receive(:puts) @@ -208,45 +203,6 @@ RSpec.describe ReviewApps::AutomatedCleanup, feature_category: :tooling do end context 'when the environment is for a review-app' do - context 'when there are no deployments' do - let(:deployments) { [] } - - context 'when the environment is already stopped' do - let(:env_state) { 'stopped' } - - it 'does not stop the environment' do - expect(gitlab_client).not_to receive(:stop_environment) - allow(gitlab_client).to receive(:delete_environment) - - subject - end - - it 'deletes the environment' do - expect(gitlab_client).to receive(:delete_environment) - - subject - end - end - - context 'when the environment is not stopped' do - let(:env_state) { 'available' } - - it 'stops the environment' do - expect(gitlab_client).to receive(:stop_environment) - allow(gitlab_client).to receive(:delete_environment) - - subject - end - - it 'deletes the environment' do - allow(gitlab_client).to receive(:stop_environment) - expect(gitlab_client).to receive(:delete_environment) - - subject - end - end - end - context 'when the environment state is stopping' do let(:env_state) { 'stopping' } @@ -263,39 +219,37 @@ RSpec.describe ReviewApps::AutomatedCleanup, feature_category: :tooling do end end - context 'when there are deployments' do - context 'when the latest deployment happened later than the days_for_delete argument' do - let(:deployment_created_at) { one_day_ago.to_s } + context 'when the environment was created later than the days_for_delete argument' do + let(:environment_created_at) { one_day_ago.to_s } - it 'does not stop the environment' do - expect(gitlab_client).not_to receive(:stop_environment) + it 'does not stop the environment' do + expect(gitlab_client).not_to receive(:stop_environment) - subject - end - - it 'does not delete the environment' do - expect(gitlab_client).not_to receive(:delete_environment) - - subject - end + subject end - context 'when the latest deployment happened earlier than the days_for_delete argument' do - let(:deployment_created_at) { three_days_ago.to_s } + it 'does not delete the environment' do + expect(gitlab_client).not_to receive(:delete_environment) - it 'stops the environment' do - expect(gitlab_client).to receive(:stop_environment) - allow(gitlab_client).to receive(:delete_environment) + subject + end + end - subject - end + context 'when the environment was created earlier than the days_for_delete argument' do + let(:environment_created_at) { three_days_ago.to_s } - it 'deletes the environment' do - allow(gitlab_client).to receive(:stop_environment) - expect(gitlab_client).to receive(:delete_environment) + it 'stops the environment' do + expect(gitlab_client).to receive(:stop_environment) + allow(gitlab_client).to receive(:delete_environment) - subject - end + subject + end + + it 'deletes the environment' do + allow(gitlab_client).to receive(:stop_environment) + expect(gitlab_client).to receive(:delete_environment) + + subject end end end diff --git a/spec/services/users/update_canonical_email_service_spec.rb b/spec/services/users/update_canonical_email_service_spec.rb index ba9a6240d15..460c04e18f0 100644 --- a/spec/services/users/update_canonical_email_service_spec.rb +++ b/spec/services/users/update_canonical_email_service_spec.rb @@ -3,10 +3,10 @@ require 'spec_helper' RSpec.describe Users::UpdateCanonicalEmailService, feature_category: :user_profile do - let(:other_email) { "differentaddress@includeddomain.com" } + let(:other_email) { "differentaddress@gmail.com" } before do - stub_const("Users::UpdateCanonicalEmailService::INCLUDED_DOMAINS_PATTERN", [/includeddomain/]) + stub_const("Users::UpdateCanonicalEmailService::INCLUDED_DOMAINS_PATTERN", [/gmail/]) end describe '#initialize' do @@ -21,8 +21,8 @@ RSpec.describe Users::UpdateCanonicalEmailService, feature_category: :user_profi end context 'when a user is provided' do - let(:user) { build(:user, email: 'user+123@includeddomain.com') } - let(:expected_canonical_email) { 'user@includeddomain.com' } + let(:user) { build(:user, email: 'user+123@gmail.com') } + let(:expected_canonical_email) { 'user@gmail.com' } subject(:service) { described_class.new(user: user) } @@ -40,11 +40,11 @@ RSpec.describe Users::UpdateCanonicalEmailService, feature_category: :user_profi context 'when the user has an existing canonical email' do it 'updates the user canonical email record' do user.user_canonical_email = build(:user_canonical_email, canonical_email: other_email) - user.email = "us.er+123@includeddomain.com" + user.email = "us.er+123@gmail.com" subject.execute - expect(user.user_canonical_email.canonical_email).to eq "user@includeddomain.com" + expect(user.user_canonical_email.canonical_email).to eq "user@gmail.com" end end diff --git a/spec/support/helpers/sharding_key_spec_helpers.rb b/spec/support/helpers/sharding_key_spec_helpers.rb index 356d6e6e64e..bcd5af383d1 100644 --- a/spec/support/helpers/sharding_key_spec_helpers.rb +++ b/spec/support/helpers/sharding_key_spec_helpers.rb @@ -67,13 +67,17 @@ module ShardingKeySpecHelpers end end - def has_foreign_key?(from_table_name, column_name, to_table_name: nil) + def has_foreign_key?(from_table_name, column_name, to_table_name: nil, foreign_key_name: nil) where_clause = { constrained_table_name: from_table_name, constrained_columns: [column_name] } where_clause[:referenced_table_name] = to_table_name if to_table_name + if foreign_key_name + where_clause[:name] = foreign_key_name + where_clause.delete(:constrained_columns) + end fk = ::Gitlab::Database::PostgresForeignKey.where(where_clause).first diff --git a/spec/tooling/danger/cookie_setting_spec.rb b/spec/tooling/danger/cookie_setting_spec.rb new file mode 100644 index 00000000000..cf1d576c7a5 --- /dev/null +++ b/spec/tooling/danger/cookie_setting_spec.rb @@ -0,0 +1,95 @@ +# frozen_string_literal: true + +require 'fast_spec_helper' +require 'rspec-parameterized' +require 'gitlab/dangerfiles/spec_helper' + +require_relative '../../../tooling/danger/cookie_setting' +require_relative '../../../tooling/danger/project_helper' + +RSpec.describe Tooling::Danger::CookieSetting, feature_category: :tooling do + include_context 'with dangerfile' + + let(:fake_danger) { DangerSpecHelper.fake_danger } + let(:fake_project_helper) { instance_double(Tooling::Danger::ProjectHelper) } + let(:comment_text) { "\n#{described_class::SUGGESTION}" } + let(:file_lines) { file_diff.map { |line| line.delete_prefix('+') } } + + before do + allow(cookie_setting).to receive(:project_helper).and_return(fake_project_helper) + allow(cookie_setting.project_helper).to receive(:file_lines).and_return(file_lines) + allow(cookie_setting.helper).to receive(:added_files).and_return([filename]) + allow(cookie_setting.helper).to receive(:changed_lines).with(filename).and_return(file_diff) + + cookie_setting.define_singleton_method(:add_suggestions_for) do |filename| + Tooling::Danger::CookieSetting.new(filename, context: self).suggest + end + end + + subject(:cookie_setting) { fake_danger.new(helper: fake_helper) } + + context 'for single line method call' do + let(:file_diff) do + <<~DIFF.split("\n") + + def index + + #{code} + + + + render text: 'OK' + + end + DIFF + end + + context 'when file is a non-spec Ruby file' do + let(:filename) { 'app/controllers/user_settings/active_sessions_controller.rb' } + + using RSpec::Parameterized::TableSyntax + + context 'when comment is expected' do + where(:code) do + [ + 'cookies[:my_key] = true', + 'cookies["my_key"] = true', + 'cookies[\'my_key\'] = true', + 'cookies[:my_key] = { value: "nbd", expires: 1.year, domain: "example.com" }', + 'cookies.encrypted[:my_key] = true', + 'cookies.permanent[:my_key] = true', + 'cookies.signed[:my_key] = true', + 'cookies.signed.encrypted.permanent[:my_key] = true', + 'cookies[Example::Class::With::CONSTANT] = true', + 'cookies[Example::Class::With::CONSTANT] = { value: "nbd", expires: 1.year, domain: "example.com" }', + 'cookies.encrypted[Example::Class::With::CONSTANT] = { value: "nbd", domain: "example.com" }', + 'cookies.permanent[Example::Class::With::CONSTANT] = { value: "nbd", domain: "example.com" }', + 'cookies.signed[Example::Class::With::CONSTANT] = { value: "nbd", domain: "example.com" }' + ] + end + + with_them do + specify do + expect(cookie_setting).to receive(:markdown).with(comment_text.chomp, file: filename, line: 2) + + cookie_setting.add_suggestions_for(filename) + end + end + end + + context 'when no comment is expected' do + where(:code) do + [ + 'cookies[:my_cookie].blank?', + 'cookies.signed[Some::Class::With::CONSTANTS].blank?', + 'cookies[:my_cookie] == "true"', + 'cookies.encrypted[:my_cookie] += "true"' + ] + end + + with_them do + specify do + expect(cookie_setting).not_to receive(:markdown) + + cookie_setting.add_suggestions_for(filename) + end + end + end + end + end +end diff --git a/tooling/danger/cookie_setting.rb b/tooling/danger/cookie_setting.rb new file mode 100644 index 00000000000..1a8c992f2ea --- /dev/null +++ b/tooling/danger/cookie_setting.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require_relative 'suggestion' + +module Tooling + module Danger + class CookieSetting < Suggestion + MATCH = %r{cookies(?:\.encrypted|\.signed|\.permanent)*\[([^\]]+)\]\s*=[^=]} + REPLACEMENT = nil + DOCUMENTATION_LINK = 'https://docs.gitlab.com/ee/development/cookies.html#cookies-on-rails' + + SUGGESTION = <<~MESSAGE_MARKDOWN.freeze + It looks like you are setting a server-side cookie. Please note that if you set + the `:domain` attribute for this cookie, you must ensure the cookie is unset when + the user logs out. Most cookies do not require this attribute. + + ---- + + For more information, see [cookies documentation](#{DOCUMENTATION_LINK}). + MESSAGE_MARKDOWN + end + end +end