Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
		
							parent
							
								
									b330f7f0bf
								
							
						
					
					
						commit
						830c9943a9
					
				|  | @ -357,7 +357,9 @@ | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   > li { |   > li { | ||||||
|     .badge.badge-pill { |     // TODO: Remove this block once all sidebar badges use gl_badge_tag | ||||||
|  |     // https://gitlab.com/gitlab-org/gitlab/-/issues/350061 | ||||||
|  |     .badge.badge-pill:not(.gl-badge) { | ||||||
|       @include gl-rounded-lg; |       @include gl-rounded-lg; | ||||||
|       @include gl-py-1; |       @include gl-py-1; | ||||||
|       @include gl-px-3; |       @include gl-px-3; | ||||||
|  | @ -370,7 +372,9 @@ | ||||||
|         display: block; |         display: block; | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       .badge.badge-pill { |       // TODO: Remove this block once all sidebar badges use gl_badge_tag | ||||||
|  |       // https://gitlab.com/gitlab-org/gitlab/-/issues/350061 | ||||||
|  |       .badge.badge-pill:not(.gl-badge) { | ||||||
|         @include gl-font-weight-normal; |         @include gl-font-weight-normal; | ||||||
|         color: $blue-700; |         color: $blue-700; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|  | @ -65,33 +65,6 @@ | ||||||
|     display: inline; |     display: inline; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   .branch-link { |  | ||||||
|     margin-bottom: 2px; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   .limit-box { |  | ||||||
|     cursor: pointer; |  | ||||||
|     display: inline-flex; |  | ||||||
|     align-items: center; |  | ||||||
|     background-color: $red-100; |  | ||||||
|     border-radius: $border-radius-default; |  | ||||||
|     text-align: center; |  | ||||||
| 
 |  | ||||||
|     &:hover { |  | ||||||
|       background-color: $red-200; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     .limit-icon { |  | ||||||
|       margin: 0 4px; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     .limit-message { |  | ||||||
|       line-height: 16px; |  | ||||||
|       margin-right: 8px; |  | ||||||
|       font-size: 12px; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   svg { |   svg { | ||||||
|     vertical-align: text-top; |     vertical-align: text-top; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | @ -314,6 +314,10 @@ h1 { | ||||||
|   padding-left: 0.6em; |   padding-left: 0.6em; | ||||||
|   border-radius: 10rem; |   border-radius: 10rem; | ||||||
| } | } | ||||||
|  | .badge-info { | ||||||
|  |   color: #fff; | ||||||
|  |   background-color: #428fdc; | ||||||
|  | } | ||||||
| .bg-transparent { | .bg-transparent { | ||||||
|   background-color: transparent !important; |   background-color: transparent !important; | ||||||
| } | } | ||||||
|  | @ -372,6 +376,24 @@ h1 { | ||||||
|   padding-left: 0.5rem; |   padding-left: 0.5rem; | ||||||
|   padding-right: 0.5rem; |   padding-right: 0.5rem; | ||||||
| } | } | ||||||
|  | .gl-badge.sm { | ||||||
|  |   padding-top: 0; | ||||||
|  |   padding-bottom: 0; | ||||||
|  | } | ||||||
|  | .gl-badge.badge-info { | ||||||
|  |   background-color: #064787; | ||||||
|  |   color: #9dc7f1; | ||||||
|  | } | ||||||
|  | a.gl-badge.badge-info.active, | ||||||
|  | a.gl-badge.badge-info:active { | ||||||
|  |   color: #e9f3fc; | ||||||
|  |   background-color: #0b5cad; | ||||||
|  | } | ||||||
|  | a.gl-badge.badge-info:active { | ||||||
|  |   box-shadow: inset 0 0 0 1px rgba(51, 51, 51, 0.8), | ||||||
|  |     0 0 0 1px rgba(51, 51, 51, 0.4), 0 0 0 4px rgba(66, 143, 220, 0.48); | ||||||
|  |   outline: none; | ||||||
|  | } | ||||||
| .gl-button .gl-badge { | .gl-button .gl-badge { | ||||||
|   top: 0; |   top: 0; | ||||||
| } | } | ||||||
|  | @ -1367,7 +1389,7 @@ input { | ||||||
|   border-radius: 4px; |   border-radius: 4px; | ||||||
|   box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08); |   box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08); | ||||||
| } | } | ||||||
| .sidebar-top-level-items > li .badge.badge-pill { | .sidebar-top-level-items > li .badge.badge-pill:not(.gl-badge) { | ||||||
|   border-radius: 0.5rem; |   border-radius: 0.5rem; | ||||||
|   padding-top: 0.125rem; |   padding-top: 0.125rem; | ||||||
|   padding-bottom: 0.125rem; |   padding-bottom: 0.125rem; | ||||||
|  | @ -1381,7 +1403,7 @@ input { | ||||||
|   .sidebar-sub-level-items:not(.is-fly-out-only) { |   .sidebar-sub-level-items:not(.is-fly-out-only) { | ||||||
|   display: block; |   display: block; | ||||||
| } | } | ||||||
| .sidebar-top-level-items > li.active .badge.badge-pill { | .sidebar-top-level-items > li.active .badge.badge-pill:not(.gl-badge) { | ||||||
|   font-weight: 400; |   font-weight: 400; | ||||||
|   color: #9dc7f1; |   color: #9dc7f1; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -295,6 +295,10 @@ h1 { | ||||||
|   padding-left: 0.6em; |   padding-left: 0.6em; | ||||||
|   border-radius: 10rem; |   border-radius: 10rem; | ||||||
| } | } | ||||||
|  | .badge-info { | ||||||
|  |   color: #fff; | ||||||
|  |   background-color: #1f75cb; | ||||||
|  | } | ||||||
| .bg-transparent { | .bg-transparent { | ||||||
|   background-color: transparent !important; |   background-color: transparent !important; | ||||||
| } | } | ||||||
|  | @ -353,6 +357,24 @@ h1 { | ||||||
|   padding-left: 0.5rem; |   padding-left: 0.5rem; | ||||||
|   padding-right: 0.5rem; |   padding-right: 0.5rem; | ||||||
| } | } | ||||||
|  | .gl-badge.sm { | ||||||
|  |   padding-top: 0; | ||||||
|  |   padding-bottom: 0; | ||||||
|  | } | ||||||
|  | .gl-badge.badge-info { | ||||||
|  |   background-color: #cbe2f9; | ||||||
|  |   color: #0b5cad; | ||||||
|  | } | ||||||
|  | a.gl-badge.badge-info.active, | ||||||
|  | a.gl-badge.badge-info:active { | ||||||
|  |   color: #033464; | ||||||
|  |   background-color: #9dc7f1; | ||||||
|  | } | ||||||
|  | a.gl-badge.badge-info:active { | ||||||
|  |   box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.8), | ||||||
|  |     0 0 0 1px rgba(255, 255, 255, 0.4), 0 0 0 4px rgba(31, 117, 203, 0.48); | ||||||
|  |   outline: none; | ||||||
|  | } | ||||||
| .gl-button .gl-badge { | .gl-button .gl-badge { | ||||||
|   top: 0; |   top: 0; | ||||||
| } | } | ||||||
|  | @ -1348,7 +1370,7 @@ input { | ||||||
|   border-radius: 4px; |   border-radius: 4px; | ||||||
|   box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08); |   box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08); | ||||||
| } | } | ||||||
| .sidebar-top-level-items > li .badge.badge-pill { | .sidebar-top-level-items > li .badge.badge-pill:not(.gl-badge) { | ||||||
|   border-radius: 0.5rem; |   border-radius: 0.5rem; | ||||||
|   padding-top: 0.125rem; |   padding-top: 0.125rem; | ||||||
|   padding-bottom: 0.125rem; |   padding-bottom: 0.125rem; | ||||||
|  | @ -1362,7 +1384,7 @@ input { | ||||||
|   .sidebar-sub-level-items:not(.is-fly-out-only) { |   .sidebar-sub-level-items:not(.is-fly-out-only) { | ||||||
|   display: block; |   display: block; | ||||||
| } | } | ||||||
| .sidebar-top-level-items > li.active .badge.badge-pill { | .sidebar-top-level-items > li.active .badge.badge-pill:not(.gl-badge) { | ||||||
|   font-weight: 400; |   font-weight: 400; | ||||||
|   color: #0b5cad; |   color: #0b5cad; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -73,9 +73,7 @@ module CommitsHelper | ||||||
| 
 | 
 | ||||||
|   # Returns a link formatted as a commit branch link |   # Returns a link formatted as a commit branch link | ||||||
|   def commit_branch_link(url, text) |   def commit_branch_link(url, text) | ||||||
|     link_to(url, class: 'badge badge-gray ref-name branch-link') do |     gl_badge_tag(text, { variant: :info, icon: 'branch' }, { href: url, class: 'gl-font-monospace gl-mb-1' }) | ||||||
|       sprite_icon('branch', size: 12, css_class: 'fork-svg') + "#{text}" |  | ||||||
|     end |  | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   # Returns the sorted alphabetically links to branches, separated by a comma |   # Returns the sorted alphabetically links to branches, separated by a comma | ||||||
|  | @ -87,9 +85,7 @@ module CommitsHelper | ||||||
| 
 | 
 | ||||||
|   # Returns a link formatted as a commit tag link |   # Returns a link formatted as a commit tag link | ||||||
|   def commit_tag_link(url, text) |   def commit_tag_link(url, text) | ||||||
|     link_to(url, class: 'badge badge-gray ref-name') do |     gl_badge_tag(text, { variant: :info, icon: 'tag' }, { href: url, class: 'gl-font-monospace' }) | ||||||
|       sprite_icon('tag', size: 12, css_class: 'gl-mr-2 vertical-align-middle') + "#{text}" |  | ||||||
|     end |  | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   # Returns the sorted links to tags, separated by a comma |   # Returns the sorted links to tags, separated by a comma | ||||||
|  |  | ||||||
|  | @ -210,6 +210,8 @@ module Ci | ||||||
| 
 | 
 | ||||||
|     validates :config, json_schema: { filename: 'ci_runner_config' } |     validates :config, json_schema: { filename: 'ci_runner_config' } | ||||||
| 
 | 
 | ||||||
|  |     validates :maintainer_note, length: { maximum: 255 } | ||||||
|  | 
 | ||||||
|     # Searches for runners matching the given query. |     # Searches for runners matching the given query. | ||||||
|     # |     # | ||||||
|     # This method uses ILIKE on PostgreSQL for the description field and performs a full match on tokens. |     # This method uses ILIKE on PostgreSQL for the description field and performs a full match on tokens. | ||||||
|  |  | ||||||
|  | @ -24,6 +24,7 @@ class CustomerRelations::Contact < ApplicationRecord | ||||||
|   validates :email, length: { maximum: 255 } |   validates :email, length: { maximum: 255 } | ||||||
|   validates :description, length: { maximum: 1024 } |   validates :description, length: { maximum: 1024 } | ||||||
|   validate :validate_email_format |   validate :validate_email_format | ||||||
|  |   validate :unique_email_for_group_hierarchy | ||||||
| 
 | 
 | ||||||
|   def self.find_ids_by_emails(group_id, emails) |   def self.find_ids_by_emails(group_id, emails) | ||||||
|     raise ArgumentError, "Cannot lookup more than #{MAX_PLUCK} emails" if emails.length > MAX_PLUCK |     raise ArgumentError, "Cannot lookup more than #{MAX_PLUCK} emails" if emails.length > MAX_PLUCK | ||||||
|  | @ -39,4 +40,14 @@ class CustomerRelations::Contact < ApplicationRecord | ||||||
| 
 | 
 | ||||||
|     self.errors.add(:email, I18n.t(:invalid, scope: 'valid_email.validations.email')) unless ValidateEmail.valid?(self.email) |     self.errors.add(:email, I18n.t(:invalid, scope: 'valid_email.validations.email')) unless ValidateEmail.valid?(self.email) | ||||||
|   end |   end | ||||||
|  | 
 | ||||||
|  |   def unique_email_for_group_hierarchy | ||||||
|  |     return unless group | ||||||
|  |     return unless email | ||||||
|  | 
 | ||||||
|  |     duplicate_email_exists = CustomerRelations::Contact | ||||||
|  |       .where(group_id: group.self_and_hierarchy.pluck(:id), email: email) | ||||||
|  |       .where.not(id: id).exists? | ||||||
|  |     self.errors.add(:email, _('contact with same email already exists in group hierarchy')) if duplicate_email_exists | ||||||
|  |   end | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -1,8 +1,5 @@ | ||||||
| .has-tooltip{ class: "limit-box limit-box-#{objects} gl-ml-2", data: { title: _('Project has too many %{label_for_message} to search') % { label_for_message: label_for_message } } } | - icon = objects == :branch ? 'fork' : 'tag' | ||||||
|   .limit-icon | - text = _('%{label_for_message} unavailable') % { label_for_message: label_for_message.capitalize } | ||||||
|     - if objects == :branch | - tooltip_title = _('Project has too many %{label_for_message} to search') % { label_for_message: label_for_message } | ||||||
|       = sprite_icon('fork', size: 12) | 
 | ||||||
|     - else | = gl_badge_tag(text, { variant: :danger, icon: icon }, { class: 'has-tooltip gl-ml-2', data: { title: tooltip_title } }) | ||||||
|       = sprite_icon('tag') |  | ||||||
|   .limit-message |  | ||||||
|     %span= _('%{label_for_message} unavailable') % { label_for_message: label_for_message.capitalize } |  | ||||||
|  |  | ||||||
|  | @ -6,8 +6,9 @@ | ||||||
| 
 | 
 | ||||||
| - if @branches.any? || @tags.any? || @tags_limit_exceeded | - if @branches.any? || @tags.any? || @tags_limit_exceeded | ||||||
|   %span |   %span | ||||||
|     = link_to "#", class: "js-details-expand badge badge-gray ref-name" do |     = gl_badge_tag(_("Expand"), | ||||||
|       = sprite_icon('ellipsis_h', size: 12, css_class: 'vertical-align-middle') |       { variant: :info, icon: 'ellipsis_h', icon_only: true }, | ||||||
|  |       { href: '#', class: 'js-details-expand gl-font-monospace' }) | ||||||
|     %span.js-details-content.hide |     %span.js-details-content.hide | ||||||
|       = commit_branches_links(@project, @branches) |       = commit_branches_links(@project, @branches) | ||||||
|       - if @tags_limit_exceeded |       - if @tags_limit_exceeded | ||||||
|  |  | ||||||
|  | @ -22,7 +22,7 @@ | ||||||
|         .row |         .row | ||||||
|           .form-group.col-sm-12 |           .form-group.col-sm-12 | ||||||
|             = f.label :role, _('Role'), class: 'label-bold' |             = f.label :role, _('Role'), class: 'label-bold' | ||||||
|             = f.select :role, ::User.roles.keys.map { |role| [role.titleize, role] }, { include_blank: _('Select a role') }, class: 'form-control js-user-role-dropdown', autofocus: true, required: true |             = f.select :role, ::User.roles.keys.map { |role| [role.titleize, role] }, { include_blank: _('Select a role') }, class: 'form-control js-user-role-dropdown', autofocus: true, required: true, data: { qa_selector: 'role_dropdown' } | ||||||
|         - if Feature.enabled?(:user_other_role_details) |         - if Feature.enabled?(:user_other_role_details) | ||||||
|           .row |           .row | ||||||
|             .form-group.col-sm-12.js-other-role-group.hidden |             .form-group.col-sm-12.js-other-role-group.hidden | ||||||
|  |  | ||||||
|  | @ -13,7 +13,7 @@ | ||||||
|       %span.nav-item-name{ **sidebar_menu.title_html_options } |       %span.nav-item-name{ **sidebar_menu.title_html_options } | ||||||
|         = sidebar_menu.title |         = sidebar_menu.title | ||||||
|       - if sidebar_menu.has_pill? |       - if sidebar_menu.has_pill? | ||||||
|         %span.badge.badge-pill.count{ **sidebar_menu.pill_html_options } |         = gl_badge_tag({ variant: :info, size: :sm }, { class: "count #{sidebar_menu.pill_html_options[:class]}" }) do | ||||||
|           = number_with_delimiter(sidebar_menu.pill_count) |           = number_with_delimiter(sidebar_menu.pill_count) | ||||||
| 
 | 
 | ||||||
|     = render partial: 'shared/nav/sidebar_submenu', locals: { sidebar_menu: sidebar_menu } |     = render partial: 'shared/nav/sidebar_submenu', locals: { sidebar_menu: sidebar_menu } | ||||||
|  |  | ||||||
|  | @ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56296 | ||||||
| rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/321948 | rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/321948 | ||||||
| milestone: '13.11' | milestone: '13.11' | ||||||
| type: development | type: development | ||||||
| group: group::access | group: group::workspace | ||||||
| default_enabled: false | default_enabled: false | ||||||
|  |  | ||||||
|  | @ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67652 | ||||||
| rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/340159 | rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/340159 | ||||||
| milestone: '14.3' | milestone: '14.3' | ||||||
| type: development | type: development | ||||||
| group: group::access | group: group::workspace | ||||||
| default_enabled: false | default_enabled: false | ||||||
|  |  | ||||||
|  | @ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57137 | ||||||
| rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/334952 | rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/334952 | ||||||
| milestone: '13.12' | milestone: '13.12' | ||||||
| type: development | type: development | ||||||
| group: group::access | group: group::workspace | ||||||
| default_enabled: false | default_enabled: false | ||||||
|  |  | ||||||
|  | @ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72662 | ||||||
| rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343619 | rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343619 | ||||||
| milestone: '14.6' | milestone: '14.6' | ||||||
| type: development | type: development | ||||||
| group: group::access | group: group::workspace | ||||||
| default_enabled: false | default_enabled: false | ||||||
|  |  | ||||||
|  | @ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61163 | ||||||
| rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331907 | rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331907 | ||||||
| milestone: '14.0' | milestone: '14.0' | ||||||
| type: development | type: development | ||||||
| group: group::access | group: group::workspace | ||||||
| default_enabled: false | default_enabled: false | ||||||
|  |  | ||||||
|  | @ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67650 | ||||||
| rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345666 | rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345666 | ||||||
| milestone: '14.6' | milestone: '14.6' | ||||||
| type: development | type: development | ||||||
| group: group::access | group: group::workspace | ||||||
| default_enabled: false | default_enabled: false | ||||||
|  |  | ||||||
|  | @ -0,0 +1,12 @@ | ||||||
|  | # frozen_string_literal: true | ||||||
|  | 
 | ||||||
|  | class AddMaintainerNoteToCiRunners < Gitlab::Database::Migration[1.0] | ||||||
|  |   enable_lock_retries! | ||||||
|  | 
 | ||||||
|  |   def change | ||||||
|  |     # rubocop:disable Migration/AddLimitToTextColumns | ||||||
|  |     # limit is added in 20220111095007_add_text_limit_to_ci_runners_maintainer_note.rb | ||||||
|  |     add_column :ci_runners, :maintainer_note, :text | ||||||
|  |     # rubocop:enable Migration/AddLimitToTextColumns | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1,13 @@ | ||||||
|  | # frozen_string_literal: true | ||||||
|  | 
 | ||||||
|  | class AddTextLimitToCiRunnersMaintainerNote < Gitlab::Database::Migration[1.0] | ||||||
|  |   disable_ddl_transaction! | ||||||
|  | 
 | ||||||
|  |   def up | ||||||
|  |     add_text_limit :ci_runners, :maintainer_note, 255 | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def down | ||||||
|  |     remove_text_limit :ci_runners, :maintainer_note | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | 0bc00cc8a5fa7cafa665ec113a4d0d1384c5acde37dfdf53ab1f5a2e1d6acb02 | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | 65259b0e71c1883b81c61354325cfeeade0013b55af8901bf707f2a94ee3a46a | ||||||
|  | @ -12177,7 +12177,9 @@ CREATE TABLE ci_runners ( | ||||||
|     public_projects_minutes_cost_factor double precision DEFAULT 0.0 NOT NULL, |     public_projects_minutes_cost_factor double precision DEFAULT 0.0 NOT NULL, | ||||||
|     private_projects_minutes_cost_factor double precision DEFAULT 1.0 NOT NULL, |     private_projects_minutes_cost_factor double precision DEFAULT 1.0 NOT NULL, | ||||||
|     config jsonb DEFAULT '{}'::jsonb NOT NULL, |     config jsonb DEFAULT '{}'::jsonb NOT NULL, | ||||||
|     executor_type smallint |     executor_type smallint, | ||||||
|  |     maintainer_note text, | ||||||
|  |     CONSTRAINT check_56f5ea8804 CHECK ((char_length(maintainer_note) <= 255)) | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
| CREATE SEQUENCE ci_runners_id_seq | CREATE SEQUENCE ci_runners_id_seq | ||||||
|  |  | ||||||
|  | @ -9,7 +9,13 @@ info: To determine the technical writer assigned to the Stage/Group associated w | ||||||
| GitLab provides a variety of tools to help operate and maintain | GitLab provides a variety of tools to help operate and maintain | ||||||
| your applications. | your applications. | ||||||
| 
 | 
 | ||||||
| ## Measure reliability and stability with metrics | ## Measure reliability and stability with metrics (DEPRECATED) | ||||||
|  | 
 | ||||||
|  | > [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/346485) in GitLab 14.7. | ||||||
|  | 
 | ||||||
|  | WARNING: | ||||||
|  | This feature is in its end-of-life process. It is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/346485) | ||||||
|  | for use in GitLab 14.7, and is planned for removal in GitLab 15.0. | ||||||
| 
 | 
 | ||||||
| Metrics help you understand the health and performance of your infrastructure, | Metrics help you understand the health and performance of your infrastructure, | ||||||
| applications, and systems by providing insights into your application's reliability, | applications, and systems by providing insights into your application's reliability, | ||||||
|  | @ -30,13 +36,13 @@ performance degrades, and manage those alerts - all within GitLab. | ||||||
| GitLab helps reduce alert fatigue for IT responders by providing tools to identify | GitLab helps reduce alert fatigue for IT responders by providing tools to identify | ||||||
| issues across multiple systems and aggregate alerts in a centralized place. Your | issues across multiple systems and aggregate alerts in a centralized place. Your | ||||||
| team needs a single, central interface where they can easily investigate alerts | team needs a single, central interface where they can easily investigate alerts | ||||||
| using metrics and logs, and promote the critical alerts to incidents. | and promote the critical alerts to incidents. | ||||||
| 
 | 
 | ||||||
| Are your alerts too noisy? Alerts configured on GitLab metrics can configured | Are your alerts too noisy? Alerts configured on GitLab metrics can configured | ||||||
| and fine-tuned in GitLab immediately following a fire-fight. | and fine-tuned in GitLab immediately following a fire-fight. | ||||||
| 
 | 
 | ||||||
| - [Manage alerts and incidents](incident_management/index.md) in GitLab. | - [Manage alerts and incidents](incident_management/index.md) in GitLab. | ||||||
| - [Configure alerts for metrics](metrics/alerts.md) in GitLab. | - [Configure alerts for metrics](metrics/alerts.md) in GitLab. (DEPRECATED) | ||||||
| - Create a [status page](incident_management/status_page.md) | - Create a [status page](incident_management/status_page.md) | ||||||
|   to communicate efficiently to your users during an incident. |   to communicate efficiently to your users during an incident. | ||||||
| 
 | 
 | ||||||
|  | @ -51,7 +57,13 @@ and the work required to fix them - all without leaving GitLab. | ||||||
| - Discover and view errors generated by your applications with | - Discover and view errors generated by your applications with | ||||||
|   [Error Tracking](error_tracking.md). |   [Error Tracking](error_tracking.md). | ||||||
| 
 | 
 | ||||||
| ## Trace application health and performance | ## Trace application health and performance (DEPRECATED) | ||||||
|  | 
 | ||||||
|  | > [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/346485) in GitLab 14.7. | ||||||
|  | 
 | ||||||
|  | WARNING: | ||||||
|  | This feature is in its end-of-life process. It is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/346485) | ||||||
|  | for use in GitLab 14.7, and is planned for removal in GitLab 15.0. | ||||||
| 
 | 
 | ||||||
| Application tracing in GitLab is a way to measure an application's performance and | Application tracing in GitLab is a way to measure an application's performance and | ||||||
| health while it's running. After configuring your application to enable tracing, you | health while it's running. After configuring your application to enable tracing, you | ||||||
|  | @ -65,7 +77,13 @@ microservices-based distributed systems - and displays results within GitLab. | ||||||
| 
 | 
 | ||||||
| - [Trace the performance and health](tracing.md) of a deployed application. | - [Trace the performance and health](tracing.md) of a deployed application. | ||||||
| 
 | 
 | ||||||
| ## Aggregate and store logs | ## Aggregate and store logs (DEPRECATED) | ||||||
|  | 
 | ||||||
|  | > [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/346485) in GitLab 14.7. | ||||||
|  | 
 | ||||||
|  | WARNING: | ||||||
|  | This feature is in its end-of-life process. It is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/346485) | ||||||
|  | for use in GitLab 14.7, and is planned for removal in GitLab 15.0. | ||||||
| 
 | 
 | ||||||
| Developers need to troubleshoot application changes in development, and incident | Developers need to troubleshoot application changes in development, and incident | ||||||
| responders need aggregated, real-time logs when troubleshooting problems with | responders need aggregated, real-time logs when troubleshooting problems with | ||||||
|  |  | ||||||
|  | @ -14,7 +14,7 @@ dast_scanner_profiles_builds: | ||||||
|   - table: ci_builds |   - table: ci_builds | ||||||
|     column: ci_build_id |     column: ci_build_id | ||||||
|     on_delete: async_delete |     on_delete: async_delete | ||||||
| dast_scanner_profiles_builds: | dast_site_profiles_builds: | ||||||
|   - table: ci_builds |   - table: ci_builds | ||||||
|     column: ci_build_id |     column: ci_build_id | ||||||
|     on_delete: async_delete |     on_delete: async_delete | ||||||
|  | @ -115,3 +115,11 @@ ci_minutes_additional_packs: | ||||||
|   - table: namespaces |   - table: namespaces | ||||||
|     column: namespace_id |     column: namespace_id | ||||||
|     on_delete: async_delete |     on_delete: async_delete | ||||||
|  | requirements_management_test_reports: | ||||||
|  |   - table: ci_builds | ||||||
|  |     column: build_id | ||||||
|  |     on_delete: async_nullify | ||||||
|  | security_scans: | ||||||
|  |   - table: ci_builds | ||||||
|  |     column: build_id | ||||||
|  |     on_delete: async_delete | ||||||
|  |  | ||||||
|  | @ -31642,12 +31642,18 @@ msgstr "" | ||||||
| msgid "SecurityOrchestration|Scan Execution" | msgid "SecurityOrchestration|Scan Execution" | ||||||
| msgstr "" | msgstr "" | ||||||
| 
 | 
 | ||||||
|  | msgid "SecurityOrchestration|Scan Result" | ||||||
|  | msgstr "" | ||||||
|  | 
 | ||||||
| msgid "SecurityOrchestration|Scan execution" | msgid "SecurityOrchestration|Scan execution" | ||||||
| msgstr "" | msgstr "" | ||||||
| 
 | 
 | ||||||
| msgid "SecurityOrchestration|Scan execution policies can only be created by project owners." | msgid "SecurityOrchestration|Scan execution policies can only be created by project owners." | ||||||
| msgstr "" | msgstr "" | ||||||
| 
 | 
 | ||||||
|  | msgid "SecurityOrchestration|Scan result" | ||||||
|  | msgstr "" | ||||||
|  | 
 | ||||||
| msgid "SecurityOrchestration|Scan to be performed %{cadence}" | msgid "SecurityOrchestration|Scan to be performed %{cadence}" | ||||||
| msgstr "" | msgstr "" | ||||||
| 
 | 
 | ||||||
|  | @ -41916,6 +41922,9 @@ msgstr "" | ||||||
| msgid "compliance violation has already been recorded" | msgid "compliance violation has already been recorded" | ||||||
| msgstr "" | msgstr "" | ||||||
| 
 | 
 | ||||||
|  | msgid "contact with same email already exists in group hierarchy" | ||||||
|  | msgstr "" | ||||||
|  | 
 | ||||||
| msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character" | msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character" | ||||||
| msgstr "" | msgstr "" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,13 +0,0 @@ | ||||||
| # frozen_string_literal: true |  | ||||||
| 
 |  | ||||||
| module Gitlab |  | ||||||
|   module Page |  | ||||||
|     module Main |  | ||||||
|       class Welcome < Chemlab::Page |  | ||||||
|         path '/users/sign_up/welcome' |  | ||||||
| 
 |  | ||||||
|         button :get_started_button |  | ||||||
|       end |  | ||||||
|     end |  | ||||||
|   end |  | ||||||
| end |  | ||||||
|  | @ -1,33 +0,0 @@ | ||||||
| # frozen_string_literal: true |  | ||||||
| 
 |  | ||||||
| module Gitlab |  | ||||||
|   module Page |  | ||||||
|     module Main |  | ||||||
|       module Welcome |  | ||||||
|         # @note Defined as +button :get_started_button+ |  | ||||||
|         # Clicks +get_started_button+ |  | ||||||
|         def get_started_button |  | ||||||
|           # This is a stub, used for indexing. The method is dynamically generated. |  | ||||||
|         end |  | ||||||
| 
 |  | ||||||
|         # @example |  | ||||||
|         #   Gitlab::Page::Main::Welcome.perform do |welcome| |  | ||||||
|         #     expect(welcome.get_started_button_element).to exist |  | ||||||
|         #   end |  | ||||||
|         # @return [Watir::Button] The raw +Button+ element |  | ||||||
|         def get_started_button_element |  | ||||||
|           # This is a stub, used for indexing. The method is dynamically generated. |  | ||||||
|         end |  | ||||||
| 
 |  | ||||||
|         # @example |  | ||||||
|         #   Gitlab::Page::Main::Welcome.perform do |welcome| |  | ||||||
|         #     expect(welcome).to be_get_started_button |  | ||||||
|         #   end |  | ||||||
|         # @return [Boolean] true if the +get_started_button+ element is present on the page |  | ||||||
|         def get_started_button? |  | ||||||
|           # This is a stub, used for indexing. The method is dynamically generated. |  | ||||||
|         end |  | ||||||
|       end |  | ||||||
|     end |  | ||||||
|   end |  | ||||||
| end |  | ||||||
|  | @ -26,9 +26,12 @@ module QA | ||||||
|           sign_up.click_new_user_register_button |           sign_up.click_new_user_register_button | ||||||
|         end |         end | ||||||
| 
 | 
 | ||||||
|         Page::Registration::Welcome.perform(&:click_get_started_button_if_available) |         Flow::UserOnboarding.onboard_user | ||||||
| 
 | 
 | ||||||
|         success = if user.expect_fabrication_success |         success = if user.expect_fabrication_success | ||||||
|  |                     # In development env and .com the user is asked to create a group and a project which can be skipped for | ||||||
|  |                     # the purpose of signing up | ||||||
|  |                     Runtime::Browser.visit(:gitlab, Page::Dashboard::Welcome) | ||||||
|                     Page::Main::Menu.perform(&:has_personal_area?) |                     Page::Main::Menu.perform(&:has_personal_area?) | ||||||
|                   else |                   else | ||||||
|                     Page::Main::Menu.perform(&:not_signed_in?) |                     Page::Main::Menu.perform(&:not_signed_in?) | ||||||
|  |  | ||||||
|  | @ -0,0 +1,19 @@ | ||||||
|  | # frozen_string_literal: true | ||||||
|  | 
 | ||||||
|  | module QA | ||||||
|  |   module Flow | ||||||
|  |     module UserOnboarding | ||||||
|  |       module_function | ||||||
|  | 
 | ||||||
|  |       def onboard_user | ||||||
|  |         Page::Registration::Welcome.perform do |welcome_page| | ||||||
|  |           if welcome_page.has_get_started_button? | ||||||
|  |             welcome_page.select_role('Other') | ||||||
|  |             welcome_page.choose_setup_for_company_if_available | ||||||
|  |             welcome_page.click_get_started_button | ||||||
|  |           end | ||||||
|  |         end | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -11,6 +11,10 @@ module QA | ||||||
|         def has_welcome_title?(text) |         def has_welcome_title?(text) | ||||||
|           has_element?(:welcome_title_content, text: text) |           has_element?(:welcome_title_content, text: text) | ||||||
|         end |         end | ||||||
|  | 
 | ||||||
|  |         def self.path | ||||||
|  |           '/' | ||||||
|  |         end | ||||||
|       end |       end | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|  |  | ||||||
|  | @ -16,10 +16,6 @@ module QA | ||||||
|           element :new_user_username_field |           element :new_user_username_field | ||||||
|         end |         end | ||||||
| 
 | 
 | ||||||
|         view 'app/views/registrations/welcome/show.html.haml' do |  | ||||||
|           element :get_started_button |  | ||||||
|         end |  | ||||||
| 
 |  | ||||||
|         def fill_new_user_first_name_field(first_name) |         def fill_new_user_first_name_field(first_name) | ||||||
|           fill_element :new_user_first_name_field, first_name |           fill_element :new_user_first_name_field, first_name | ||||||
|         end |         end | ||||||
|  |  | ||||||
|  | @ -6,14 +6,25 @@ module QA | ||||||
|       class Welcome < Page::Base |       class Welcome < Page::Base | ||||||
|         view 'app/views/registrations/welcome/show.html.haml' do |         view 'app/views/registrations/welcome/show.html.haml' do | ||||||
|           element :get_started_button |           element :get_started_button | ||||||
|  |           element :role_dropdown | ||||||
|         end |         end | ||||||
| 
 | 
 | ||||||
|         def click_get_started_button_if_available |         def has_get_started_button? | ||||||
|           if has_element?(:get_started_button) |           has_element?(:get_started_button) | ||||||
|             Support::Retrier.retry_until do |         end | ||||||
|               click_element :get_started_button | 
 | ||||||
|               has_no_element?(:get_started_button) |         def select_role(role) | ||||||
|             end |           select_element(:role_dropdown, role) | ||||||
|  |         end | ||||||
|  | 
 | ||||||
|  |         def choose_setup_for_company_if_available | ||||||
|  |           # Only implemented in EE | ||||||
|  |         end | ||||||
|  | 
 | ||||||
|  |         def click_get_started_button | ||||||
|  |           Support::Retrier.retry_until do | ||||||
|  |             click_element :get_started_button | ||||||
|  |             has_no_element?(:get_started_button) | ||||||
|           end |           end | ||||||
|         end |         end | ||||||
|       end |       end | ||||||
|  |  | ||||||
|  | @ -90,6 +90,20 @@ module QA | ||||||
|         enabled?(ENV['ACCEPT_INSECURE_CERTS']) |         enabled?(ENV['ACCEPT_INSECURE_CERTS']) | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|  |       def running_on_dot_com? | ||||||
|  |         uri = URI.parse(Runtime::Scenario.gitlab_address) | ||||||
|  |         uri.host.include?('.com') | ||||||
|  |       end | ||||||
|  | 
 | ||||||
|  |       def running_on_dev? | ||||||
|  |         uri = URI.parse(Runtime::Scenario.gitlab_address) | ||||||
|  |         uri.port != 80 && uri.port != 443 | ||||||
|  |       end | ||||||
|  | 
 | ||||||
|  |       def running_on_dev_or_dot_com? | ||||||
|  |         running_on_dev? || running_on_dot_com? | ||||||
|  |       end | ||||||
|  | 
 | ||||||
|       def running_in_ci? |       def running_in_ci? | ||||||
|         ENV['CI'] || ENV['CI_SERVER'] |         ENV['CI'] || ENV['CI_SERVER'] | ||||||
|       end |       end | ||||||
|  |  | ||||||
|  | @ -13,7 +13,7 @@ module QA | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   RSpec.describe 'Manage', :skip_signup_disabled, :requires_admin do |   RSpec.describe 'Manage', :skip_signup_disabled, :requires_admin, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/349626', type: :stale } do | ||||||
|     describe 'while LDAP is enabled', :orchestrated, :ldap_no_tls, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347934' do |     describe 'while LDAP is enabled', :orchestrated, :ldap_no_tls, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347934' do | ||||||
|       before do |       before do | ||||||
|         # When LDAP is enabled, a previous test might have created a token for the LDAP 'tanuki' user who is not an admin |         # When LDAP is enabled, a previous test might have created a token for the LDAP 'tanuki' user who is not an admin | ||||||
|  | @ -118,11 +118,12 @@ module QA | ||||||
| 
 | 
 | ||||||
|           Flow::Login.sign_in(as: @user, skip_page_validation: true) |           Flow::Login.sign_in(as: @user, skip_page_validation: true) | ||||||
| 
 | 
 | ||||||
|           Page::Registration::Welcome.perform(&:click_get_started_button_if_available) |           Flow::UserOnboarding.onboard_user | ||||||
| 
 | 
 | ||||||
|           Page::Main::Menu.perform do |menu| |           # In development env and .com the user is asked to create a group and a project which can be skipped for | ||||||
|             expect(menu).to have_personal_area |           # the purpose of this test | ||||||
|           end |           Runtime::Browser.visit(:gitlab, Page::Dashboard::Welcome) | ||||||
|  |           Page::Main::Menu.perform(&:has_personal_area?) | ||||||
|         end |         end | ||||||
| 
 | 
 | ||||||
|         after do |         after do | ||||||
|  |  | ||||||
|  | @ -83,6 +83,46 @@ RSpec.describe QA::Runtime::Env do | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|  |   describe '.running_on_dot_com?' do | ||||||
|  |     using RSpec::Parameterized::TableSyntax | ||||||
|  | 
 | ||||||
|  |     where(:url, :result) do | ||||||
|  |       'https://www.gitlab.com'     | true | ||||||
|  |       'https://staging.gitlab.com' | true | ||||||
|  |       'http://www.gitlab.com'      | true | ||||||
|  |       'http://localhost:3000'      | false | ||||||
|  |       'http://localhost'           | false | ||||||
|  |       'http://gdk.test:3000'       | false | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     with_them do | ||||||
|  |       before do | ||||||
|  |         QA::Runtime::Scenario.define(:gitlab_address, url) | ||||||
|  |       end | ||||||
|  | 
 | ||||||
|  |       it { expect(described_class.running_on_dot_com?).to eq result } | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   describe '.running_on_dev?' do | ||||||
|  |     using RSpec::Parameterized::TableSyntax | ||||||
|  | 
 | ||||||
|  |     where(:url, :result) do | ||||||
|  |       'https://www.gitlab.com' | false | ||||||
|  |       'http://localhost:3000'  | true | ||||||
|  |       'http://localhost'       | false | ||||||
|  |       'http://gdk.test:3000'   | true | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     with_them do | ||||||
|  |       before do | ||||||
|  |         QA::Runtime::Scenario.define(:gitlab_address, url) | ||||||
|  |       end | ||||||
|  | 
 | ||||||
|  |       it { expect(described_class.running_on_dev?).to eq result } | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|   describe '.personal_access_token' do |   describe '.personal_access_token' do | ||||||
|     around do |example| |     around do |example| | ||||||
|       described_class.instance_variable_set(:@personal_access_token, nil) |       described_class.instance_variable_set(:@personal_access_token, nil) | ||||||
|  |  | ||||||
|  | @ -26,6 +26,38 @@ RSpec.describe CustomerRelations::Contact, type: :model do | ||||||
|     it_behaves_like 'an object with RFC3696 compliant email-formatted attributes', :email |     it_behaves_like 'an object with RFC3696 compliant email-formatted attributes', :email | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|  |   describe '#unique_email_for_group_hierarchy' do | ||||||
|  |     let_it_be(:parent) { create(:group) } | ||||||
|  |     let_it_be(:group) { create(:group, parent: parent) } | ||||||
|  |     let_it_be(:subgroup) { create(:group, parent: group) } | ||||||
|  | 
 | ||||||
|  |     let_it_be(:existing_contact) { create(:contact, group: group) } | ||||||
|  | 
 | ||||||
|  |     context 'with unique email for group hierarchy' do | ||||||
|  |       subject { build(:contact, group: group) } | ||||||
|  | 
 | ||||||
|  |       it { is_expected.to be_valid } | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     context 'with duplicate email in group' do | ||||||
|  |       subject { build(:contact, email: existing_contact.email, group: group) } | ||||||
|  | 
 | ||||||
|  |       it { is_expected.to be_invalid } | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     context 'with duplicate email in parent group' do | ||||||
|  |       subject { build(:contact, email: existing_contact.email, group: subgroup) } | ||||||
|  | 
 | ||||||
|  |       it { is_expected.to be_invalid } | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     context 'with duplicate email in subgroup' do | ||||||
|  |       subject { build(:contact, email: existing_contact.email, group: parent) } | ||||||
|  | 
 | ||||||
|  |       it { is_expected.to be_invalid } | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|   describe '#before_validation' do |   describe '#before_validation' do | ||||||
|     it 'strips leading and trailing whitespace' do |     it 'strips leading and trailing whitespace' do | ||||||
|       contact = described_class.new(first_name: '  First  ', last_name: ' Last  ', phone: '  123456 ') |       contact = described_class.new(first_name: '  First  ', last_name: ' Last  ', phone: '  123456 ') | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue