Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
6faeb44a01
commit
7b29a4f84e
|
@ -17,10 +17,10 @@ module Pajamas
|
||||||
@avatar_options = avatar_options
|
@avatar_options = avatar_options
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
SIZE_OPTIONS = [16, 24, 32, 48, 64, 96].freeze
|
SIZE_OPTIONS = [16, 24, 32, 48, 64, 96].freeze
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
def avatar_classes
|
def avatar_classes
|
||||||
classes = ["gl-avatar", "gl-avatar-s#{@size}", @class]
|
classes = ["gl-avatar", "gl-avatar-s#{@size}", @class]
|
||||||
classes.push("gl-avatar-circle") if @record.is_a?(User)
|
classes.push("gl-avatar-circle") if @record.is_a?(User)
|
||||||
|
|
|
@ -22,11 +22,11 @@ module Pajamas
|
||||||
@html_options = html_options
|
@html_options = html_options
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
SIZE_OPTIONS = [:sm, :md, :lg].freeze
|
SIZE_OPTIONS = [:sm, :md, :lg].freeze
|
||||||
VARIANT_OPTIONS = [:muted, :neutral, :info, :success, :warning, :danger].freeze
|
VARIANT_OPTIONS = [:muted, :neutral, :info, :success, :warning, :danger].freeze
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
delegate :sprite_icon, to: :helpers
|
delegate :sprite_icon, to: :helpers
|
||||||
|
|
||||||
def badge_classes
|
def badge_classes
|
||||||
|
|
|
@ -23,13 +23,15 @@ module Pajamas
|
||||||
@button_text = button_text
|
@button_text = button_text
|
||||||
@button_link = button_link
|
@button_link = button_link
|
||||||
@embedded = embedded
|
@embedded = embedded
|
||||||
@variant = variant.to_sym
|
@variant = filter_attribute(variant.to_sym, VARIANT_OPTIONS, default: :promotion)
|
||||||
@svg_path = svg_path.to_s
|
@svg_path = svg_path.to_s
|
||||||
@banner_options = banner_options
|
@banner_options = banner_options
|
||||||
@button_options = button_options
|
@button_options = button_options
|
||||||
@close_options = close_options
|
@close_options = close_options
|
||||||
end
|
end
|
||||||
|
|
||||||
|
VARIANT_OPTIONS = [:introduction, :promotion].freeze
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def banner_class
|
def banner_class
|
||||||
|
|
|
@ -14,15 +14,15 @@ module Pajamas
|
||||||
@html_options = html_options
|
@html_options = html_options
|
||||||
end
|
end
|
||||||
|
|
||||||
|
COLOR_OPTIONS = [:light, :dark].freeze
|
||||||
|
SIZE_OPTIONS = [:sm, :md, :lg, :xl].freeze
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def spinner_class
|
def spinner_class
|
||||||
["gl-spinner", "gl-spinner-#{@size}", "gl-spinner-#{@color} gl-vertical-align-text-bottom!"]
|
["gl-spinner", "gl-spinner-#{@size}", "gl-spinner-#{@color} gl-vertical-align-text-bottom!"]
|
||||||
end
|
end
|
||||||
|
|
||||||
COLOR_OPTIONS = [:light, :dark].freeze
|
|
||||||
SIZE_OPTIONS = [:sm, :md, :lg, :xl].freeze
|
|
||||||
|
|
||||||
def html_options
|
def html_options
|
||||||
options = format_options(options: @html_options, css_classes: "gl-spinner-container")
|
options = format_options(options: @html_options, css_classes: "gl-spinner-container")
|
||||||
options[:role] = "status"
|
options[:role] = "status"
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Distinguish between a top level query and a subselect.
|
||||||
|
#
|
||||||
|
# Retrieve column values when the relation has already been loaded, otherwise reselect the relation.
|
||||||
|
# Useful for preload query patterns where the typical Rails #preload does not fit. Such as:
|
||||||
|
#
|
||||||
|
# projects = Project.where(...)
|
||||||
|
# projects.load
|
||||||
|
# ...
|
||||||
|
# options[members] = ProjectMember.where(...).where(source_id: projects.select(:id))
|
||||||
|
module Subquery
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
class_methods do
|
||||||
|
def subquery(*column_names, max_limit: 5_000)
|
||||||
|
if current_scope.loaded? && current_scope.size <= max_limit
|
||||||
|
current_scope.pluck(*column_names)
|
||||||
|
else
|
||||||
|
current_scope.reselect(*column_names)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -7,9 +7,11 @@ module Preloaders
|
||||||
def initialize(projects, user)
|
def initialize(projects, user)
|
||||||
@projects = if projects.is_a?(Array)
|
@projects = if projects.is_a?(Array)
|
||||||
Project.where(id: projects)
|
Project.where(id: projects)
|
||||||
else
|
elsif Feature.enabled?(:projects_preloader_fix)
|
||||||
# Push projects base query in to a sub-select to avoid
|
# Push projects base query in to a sub-select to avoid
|
||||||
# table name clashes. Performs better than aliasing.
|
# table name clashes. Performs better than aliasing.
|
||||||
|
Project.where(id: projects.subquery(:id))
|
||||||
|
else
|
||||||
Project.where(id: projects.reselect(:id))
|
Project.where(id: projects.reselect(:id))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@ class Project < ApplicationRecord
|
||||||
include BulkUsersByEmailLoad
|
include BulkUsersByEmailLoad
|
||||||
include RunnerTokenExpirationInterval
|
include RunnerTokenExpirationInterval
|
||||||
include BlocksUnsafeSerialization
|
include BlocksUnsafeSerialization
|
||||||
|
include Subquery
|
||||||
|
|
||||||
extend Gitlab::Cache::RequestCache
|
extend Gitlab::Cache::RequestCache
|
||||||
extend Gitlab::Utils::Override
|
extend Gitlab::Utils::Override
|
||||||
|
|
|
@ -50,8 +50,6 @@ module IncidentManagement
|
||||||
end
|
end
|
||||||
|
|
||||||
def change_severity(incident, user)
|
def change_severity(incident, user)
|
||||||
return if Feature.disabled?(:incident_timeline_events_for_severity, incident.project)
|
|
||||||
|
|
||||||
severity_label = IssuableSeverity::SEVERITY_LABELS[incident.severity.to_sym]
|
severity_label = IssuableSeverity::SEVERITY_LABELS[incident.severity.to_sym]
|
||||||
note = "@#{user.username} changed the incident severity to **#{severity_label}**"
|
note = "@#{user.username} changed the incident severity to **#{severity_label}**"
|
||||||
occurred_at = incident.updated_at
|
occurred_at = incident.updated_at
|
||||||
|
|
|
@ -1,5 +1,14 @@
|
||||||
%head
|
%head
|
||||||
|
- if params[:lookbook][:display][:theme] == 'light'
|
||||||
= stylesheet_link_tag "application"
|
= stylesheet_link_tag "application"
|
||||||
= stylesheet_link_tag "application_utilities"
|
= stylesheet_link_tag "application_utilities"
|
||||||
%body{ style: "background-color: #{params.dig(:lookbook, :display, :bg_color) || 'white'}" }
|
- else
|
||||||
.container.gl-mt-6= yield
|
= stylesheet_link_tag "application_dark"
|
||||||
|
= stylesheet_link_tag "application_utilities_dark"
|
||||||
|
%body
|
||||||
|
.container.gl-mt-6
|
||||||
|
- if params[:lookbook][:display][:bg_dark]
|
||||||
|
.bg-dark.rounded.shadow.p-4
|
||||||
|
= yield
|
||||||
|
- else
|
||||||
|
= yield
|
||||||
|
|
|
@ -17,7 +17,6 @@ module Projects
|
||||||
return unless project
|
return unless project
|
||||||
|
|
||||||
create_prometheus_integration(project)
|
create_prometheus_integration(project)
|
||||||
create_incident_management_timeline_event_tags(project)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -51,6 +51,10 @@ Rails.application.configure do
|
||||||
config.autoload_paths.push("#{config.root}/spec/components/previews")
|
config.autoload_paths.push("#{config.root}/spec/components/previews")
|
||||||
|
|
||||||
config.lookbook.page_paths = ["#{config.root}/spec/components/docs"]
|
config.lookbook.page_paths = ["#{config.root}/spec/components/docs"]
|
||||||
|
config.lookbook.preview_params_options_eval = true
|
||||||
|
config.lookbook.preview_display_options = {
|
||||||
|
theme: ["light", "dark (alpha)"]
|
||||||
|
}
|
||||||
|
|
||||||
# Adds additional error checking when serving assets at runtime.
|
# Adds additional error checking when serving assets at runtime.
|
||||||
# Checks for improperly declared sprockets dependencies.
|
# Checks for improperly declared sprockets dependencies.
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
name: incident_timeline_events_for_severity
|
name: projects_preloader_fix
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/100954
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96108
|
||||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/378408
|
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/378858
|
||||||
milestone: '15.6'
|
milestone: '15.6'
|
||||||
type: development
|
type: development
|
||||||
group: group::respond
|
group: group::workspace
|
||||||
default_enabled: false
|
default_enabled: false
|
|
@ -1,8 +0,0 @@
|
||||||
---
|
|
||||||
name: split_background_migration_on_query_canceled
|
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/101825
|
|
||||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/378846
|
|
||||||
milestone: '15.6'
|
|
||||||
type: development
|
|
||||||
group: group::database
|
|
||||||
default_enabled: false
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class ChangeVulnerabilityFeedbackUniqueIdx < Gitlab::Database::Migration[2.0]
|
||||||
|
NEW_INDEX_NAME = :index_vulnerability_feedback_on_common_attributes
|
||||||
|
OLD_INDEX_NAME = :vulnerability_feedback_unique_idx
|
||||||
|
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
def up
|
||||||
|
add_concurrent_index :vulnerability_feedback,
|
||||||
|
%i[project_id category feedback_type project_fingerprint],
|
||||||
|
name: NEW_INDEX_NAME
|
||||||
|
|
||||||
|
remove_concurrent_index_by_name :vulnerability_feedback, OLD_INDEX_NAME
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
add_concurrent_index :vulnerability_feedback,
|
||||||
|
%i[project_id category feedback_type project_fingerprint],
|
||||||
|
name: OLD_INDEX_NAME,
|
||||||
|
unique: true
|
||||||
|
|
||||||
|
remove_concurrent_index_by_name :vulnerability_feedback, NEW_INDEX_NAME
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,15 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class AddIndexForFindingUuidAndFeedbackTypeOnFeedback < Gitlab::Database::Migration[2.0]
|
||||||
|
INDEX_NAME = :index_vulnerability_feedback_on_feedback_type_and_finding_uuid
|
||||||
|
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
def up
|
||||||
|
add_concurrent_index :vulnerability_feedback, %i[feedback_type finding_uuid], name: INDEX_NAME
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
remove_concurrent_index_by_name :vulnerability_feedback, INDEX_NAME
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,13 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class TruncateTimelineEventTagsTable < Gitlab::Database::Migration[2.0]
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
def up
|
||||||
|
execute('TRUNCATE TABLE incident_management_timeline_event_tags, incident_management_timeline_event_tag_links')
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
# no-op
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1 @@
|
||||||
|
951ad9faf483d58778cd831a0ac949473d6eeb753322754eff3f02756d757583
|
|
@ -0,0 +1 @@
|
||||||
|
2185444f733eec25a2741764619516eecb1d2c6e3e4ec3b3ed5b72bfd9c4db46
|
|
@ -0,0 +1 @@
|
||||||
|
b8438bebe77ae835b754431d8d67c306714205bef11826a15d4c84d7b67a3581
|
|
@ -30970,6 +30970,10 @@ CREATE INDEX index_vulnerability_feedback_on_author_id ON vulnerability_feedback
|
||||||
|
|
||||||
CREATE INDEX index_vulnerability_feedback_on_comment_author_id ON vulnerability_feedback USING btree (comment_author_id);
|
CREATE INDEX index_vulnerability_feedback_on_comment_author_id ON vulnerability_feedback USING btree (comment_author_id);
|
||||||
|
|
||||||
|
CREATE INDEX index_vulnerability_feedback_on_common_attributes ON vulnerability_feedback USING btree (project_id, category, feedback_type, project_fingerprint);
|
||||||
|
|
||||||
|
CREATE INDEX index_vulnerability_feedback_on_feedback_type_and_finding_uuid ON vulnerability_feedback USING btree (feedback_type, finding_uuid);
|
||||||
|
|
||||||
CREATE INDEX index_vulnerability_feedback_on_issue_id ON vulnerability_feedback USING btree (issue_id);
|
CREATE INDEX index_vulnerability_feedback_on_issue_id ON vulnerability_feedback USING btree (issue_id);
|
||||||
|
|
||||||
CREATE INDEX index_vulnerability_feedback_on_issue_id_not_null ON vulnerability_feedback USING btree (id) WHERE (issue_id IS NOT NULL);
|
CREATE INDEX index_vulnerability_feedback_on_issue_id_not_null ON vulnerability_feedback USING btree (id) WHERE (issue_id IS NOT NULL);
|
||||||
|
@ -31258,8 +31262,6 @@ CREATE INDEX user_follow_users_followee_id_idx ON user_follow_users USING btree
|
||||||
|
|
||||||
CREATE INDEX users_forbidden_state_idx ON users USING btree (id) WHERE ((confirmed_at IS NOT NULL) AND ((state)::text <> ALL (ARRAY['blocked'::text, 'banned'::text, 'ldap_blocked'::text])));
|
CREATE INDEX users_forbidden_state_idx ON users USING btree (id) WHERE ((confirmed_at IS NOT NULL) AND ((state)::text <> ALL (ARRAY['blocked'::text, 'banned'::text, 'ldap_blocked'::text])));
|
||||||
|
|
||||||
CREATE UNIQUE INDEX vulnerability_feedback_unique_idx ON vulnerability_feedback USING btree (project_id, category, feedback_type, project_fingerprint);
|
|
||||||
|
|
||||||
CREATE UNIQUE INDEX vulnerability_occurrence_pipelines_on_unique_keys ON vulnerability_occurrence_pipelines USING btree (occurrence_id, pipeline_id);
|
CREATE UNIQUE INDEX vulnerability_occurrence_pipelines_on_unique_keys ON vulnerability_occurrence_pipelines USING btree (occurrence_id, pipeline_id);
|
||||||
|
|
||||||
CREATE UNIQUE INDEX work_item_types_namespace_id_and_name_unique ON work_item_types USING btree (namespace_id, btrim(lower(name)));
|
CREATE UNIQUE INDEX work_item_types_namespace_id_and_name_unique ON work_item_types USING btree (namespace_id, btrim(lower(name)));
|
||||||
|
|
|
@ -76,13 +76,7 @@ The comment is shown on the incident timeline as a timeline event.
|
||||||
|
|
||||||
### When incident severity changes
|
### When incident severity changes
|
||||||
|
|
||||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/375280) in GitLab 15.6 [with a flag](../../administration/feature_flags.md) named `incident_timeline_events_for_severity`. Disabled by default. Enabled on GitLab.com.
|
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/375280) in GitLab 15.6.
|
||||||
|
|
||||||
FLAG:
|
|
||||||
On self-managed GitLab, by default this feature is unavailable. To show the feature per user,
|
|
||||||
ask an administrator to [enable the feature flag](../../administration/feature_flags.md) named `incident_timeline_events_for_severity`.
|
|
||||||
On GitLab.com, this feature is available.
|
|
||||||
This feature is not ready for production use.
|
|
||||||
|
|
||||||
A new timeline event is created when someone [changes the severity](incidents.md#change-severity)
|
A new timeline event is created when someone [changes the severity](incidents.md#change-severity)
|
||||||
of an incident.
|
of an incident.
|
||||||
|
|
|
@ -146,7 +146,7 @@ To disable analyzer rules:
|
||||||
1. Create a custom ruleset file named `sast-ruleset.toml` in the `.gitlab` directory, if
|
1. Create a custom ruleset file named `sast-ruleset.toml` in the `.gitlab` directory, if
|
||||||
one doesn't already exist.
|
one doesn't already exist.
|
||||||
1. Set the `disabled` flag to `true` in the context of a `ruleset` section.
|
1. Set the `disabled` flag to `true` in the context of a `ruleset` section.
|
||||||
1. In one or more `ruleset.identifier` subsections, list the rules to disable. Every
|
1. In one or more `ruleset` subsections, list the rules to disable. Every
|
||||||
`ruleset.identifier` section has:
|
`ruleset.identifier` section has:
|
||||||
- A `type` field for the rule. For IaC Scanning, the identifier type is `kics_id`.
|
- A `type` field for the rule. For IaC Scanning, the identifier type is `kics_id`.
|
||||||
- A `value` field for the rule identifier. KICS rule identifiers are alphanumeric strings. To find the rule identifier, you can:
|
- A `value` field for the rule identifier. KICS rule identifiers are alphanumeric strings. To find the rule identifier, you can:
|
||||||
|
@ -163,6 +163,12 @@ the `kics` analyzer by matching the `type` and `value` of identifiers:
|
||||||
[kics.ruleset.identifier]
|
[kics.ruleset.identifier]
|
||||||
type = "kics_id"
|
type = "kics_id"
|
||||||
value = "8212e2d7-e683-49bc-bf78-d6799075c5a7"
|
value = "8212e2d7-e683-49bc-bf78-d6799075c5a7"
|
||||||
|
|
||||||
|
[[kics.ruleset]]
|
||||||
|
disable = true
|
||||||
|
[kics.ruleset.identifier]
|
||||||
|
type = "kics_id"
|
||||||
|
value = "b03a748a-542d-44f4-bb86-9199ab4fd2d5"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Override predefined analyzer rules
|
### Override predefined analyzer rules
|
||||||
|
|
|
@ -60,6 +60,8 @@ module API
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.postload_relation(projects_relation, options = {}) end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
alias_method :project, :object
|
alias_method :project, :object
|
||||||
|
|
|
@ -25,6 +25,9 @@ module API
|
||||||
|
|
||||||
# rubocop: disable CodeReuse/ActiveRecord
|
# rubocop: disable CodeReuse/ActiveRecord
|
||||||
def self.preload_relation(projects_relation, options = {})
|
def self.preload_relation(projects_relation, options = {})
|
||||||
|
if ::Feature.enabled?(:projects_preloader_fix)
|
||||||
|
super(projects_relation, options)
|
||||||
|
else
|
||||||
relation = super(projects_relation, options)
|
relation = super(projects_relation, options)
|
||||||
# use reselect to override the existing select and
|
# use reselect to override the existing select and
|
||||||
# prevent an error `subquery has too many columns`
|
# prevent an error `subquery has too many columns`
|
||||||
|
@ -43,6 +46,21 @@ module API
|
||||||
|
|
||||||
relation
|
relation
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.postload_relation(projects_relation, options = {})
|
||||||
|
return unless ::Feature.enabled?(:projects_preloader_fix)
|
||||||
|
|
||||||
|
options[:project_members] = options[:current_user]
|
||||||
|
.project_members
|
||||||
|
.where(source_id: projects_relation.subquery(:id))
|
||||||
|
.preload(:source, user: [notification_settings: :source])
|
||||||
|
|
||||||
|
options[:group_members] = options[:current_user]
|
||||||
|
.group_members
|
||||||
|
.where(source_id: projects_relation.subquery(:namespace_id))
|
||||||
|
.preload(:source, user: [notification_settings: :source])
|
||||||
|
end
|
||||||
# rubocop: enable CodeReuse/ActiveRecord
|
# rubocop: enable CodeReuse/ActiveRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,6 +10,8 @@ module API
|
||||||
|
|
||||||
execute_batch_counting(projects_relation)
|
execute_batch_counting(projects_relation)
|
||||||
|
|
||||||
|
postload_relation(projects_relation, options)
|
||||||
|
|
||||||
preload_repository_cache(projects_relation)
|
preload_repository_cache(projects_relation)
|
||||||
|
|
||||||
Preloaders::UserMaxAccessLevelInProjectsPreloader.new(projects_relation, options[:current_user]).execute if options[:current_user]
|
Preloaders::UserMaxAccessLevelInProjectsPreloader.new(projects_relation, options[:current_user]).execute if options[:current_user]
|
||||||
|
|
|
@ -14,7 +14,8 @@ module Gitlab
|
||||||
MAX_ATTEMPTS = 3
|
MAX_ATTEMPTS = 3
|
||||||
STUCK_JOBS_TIMEOUT = 1.hour.freeze
|
STUCK_JOBS_TIMEOUT = 1.hour.freeze
|
||||||
TIMEOUT_EXCEPTIONS = [ActiveRecord::StatementTimeout, ActiveRecord::ConnectionTimeoutError,
|
TIMEOUT_EXCEPTIONS = [ActiveRecord::StatementTimeout, ActiveRecord::ConnectionTimeoutError,
|
||||||
ActiveRecord::AdapterTimeout, ActiveRecord::LockWaitTimeout].freeze
|
ActiveRecord::AdapterTimeout, ActiveRecord::LockWaitTimeout,
|
||||||
|
ActiveRecord::QueryCanceled].freeze
|
||||||
|
|
||||||
belongs_to :batched_migration, foreign_key: :batched_background_migration_id
|
belongs_to :batched_migration, foreign_key: :batched_background_migration_id
|
||||||
has_many :batched_job_transition_logs, foreign_key: :batched_background_migration_job_id
|
has_many :batched_job_transition_logs, foreign_key: :batched_background_migration_job_id
|
||||||
|
@ -112,7 +113,10 @@ module Gitlab
|
||||||
end
|
end
|
||||||
|
|
||||||
def can_split?(exception)
|
def can_split?(exception)
|
||||||
attempts >= MAX_ATTEMPTS && timeout_exception?(exception&.class) && batch_size > sub_batch_size && batch_size > 1
|
attempts >= MAX_ATTEMPTS &&
|
||||||
|
exception&.class&.in?(TIMEOUT_EXCEPTIONS) &&
|
||||||
|
batch_size > sub_batch_size &&
|
||||||
|
batch_size > 1
|
||||||
end
|
end
|
||||||
|
|
||||||
def split_and_retry!
|
def split_and_retry!
|
||||||
|
@ -161,15 +165,6 @@ module Gitlab
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def timeout_exception?(exception_class)
|
|
||||||
return false unless exception_class
|
|
||||||
|
|
||||||
TIMEOUT_EXCEPTIONS.include?(exception_class) ||
|
|
||||||
(Feature.enabled?(:split_background_migration_on_query_canceled) && exception_class == ActiveRecord::QueryCanceled)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -41,11 +41,11 @@ gitlab:
|
||||||
migrations:
|
migrations:
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
cpu: 200m
|
|
||||||
memory: 500Mi
|
|
||||||
limits:
|
|
||||||
cpu: 400m
|
cpu: 400m
|
||||||
memory: 1000Mi
|
memory: 920Mi
|
||||||
|
limits:
|
||||||
|
cpu: 600m
|
||||||
|
memory: 1100Mi
|
||||||
gitlab-shell:
|
gitlab-shell:
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
|
|
|
@ -4,7 +4,7 @@ module Pajamas
|
||||||
# @param title text
|
# @param title text
|
||||||
# @param body text
|
# @param body text
|
||||||
# @param dismissible toggle
|
# @param dismissible toggle
|
||||||
# @param variant select [info, warning, success, danger, tip]
|
# @param variant select {{ Pajamas::AlertComponent::VARIANT_ICONS.keys }}
|
||||||
def default(title: "Alert title (optional)", body: "Alert message goes here.", dismissible: true, variant: :info)
|
def default(title: "Alert title (optional)", body: "Alert message goes here.", dismissible: true, variant: :info)
|
||||||
render(Pajamas::AlertComponent.new(
|
render(Pajamas::AlertComponent.new(
|
||||||
title: title,
|
title: title,
|
||||||
|
|
|
@ -9,17 +9,17 @@ module Pajamas
|
||||||
end
|
end
|
||||||
|
|
||||||
# We show user avatars in a circle.
|
# We show user avatars in a circle.
|
||||||
# @param size select [16, 24, 32, 48, 64, 96]
|
# @param size select {{ Pajamas::AvatarComponent::SIZE_OPTIONS }}
|
||||||
def user(size: 64)
|
def user(size: 64)
|
||||||
render(Pajamas::AvatarComponent.new(User.first, size: size))
|
render(Pajamas::AvatarComponent.new(User.first, size: size))
|
||||||
end
|
end
|
||||||
|
|
||||||
# @param size select [16, 24, 32, 48, 64, 96]
|
# @param size select {{ Pajamas::AvatarComponent::SIZE_OPTIONS }}
|
||||||
def project(size: 64)
|
def project(size: 64)
|
||||||
render(Pajamas::AvatarComponent.new(Project.first, size: size))
|
render(Pajamas::AvatarComponent.new(Project.first, size: size))
|
||||||
end
|
end
|
||||||
|
|
||||||
# @param size select [16, 24, 32, 48, 64, 96]
|
# @param size select {{ Pajamas::AvatarComponent::SIZE_OPTIONS }}
|
||||||
def group(size: 64)
|
def group(size: 64)
|
||||||
render(Pajamas::AvatarComponent.new(Group.first, size: size))
|
render(Pajamas::AvatarComponent.new(Group.first, size: size))
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,9 +10,9 @@ module Pajamas
|
||||||
# @param icon select [~, star-o, issue-closed, tanuki]
|
# @param icon select [~, star-o, issue-closed, tanuki]
|
||||||
# @param icon_only toggle
|
# @param icon_only toggle
|
||||||
# @param href url
|
# @param href url
|
||||||
# @param size select [sm, md, lg]
|
# @param size select {{ Pajamas::BadgeComponent::SIZE_OPTIONS }}
|
||||||
# @param text text
|
# @param text text
|
||||||
# @param variant select [muted, neutral, info, success, warning, danger]
|
# @param variant select {{ Pajamas::BadgeComponent::VARIANT_OPTIONS }}
|
||||||
def default(icon: :tanuki, icon_only: false, href: nil, size: :md, text: "Tanuki", variant: :muted)
|
def default(icon: :tanuki, icon_only: false, href: nil, size: :md, text: "Tanuki", variant: :muted)
|
||||||
render Pajamas::BadgeComponent.new(
|
render Pajamas::BadgeComponent.new(
|
||||||
text,
|
text,
|
||||||
|
|
|
@ -9,7 +9,7 @@ module Pajamas
|
||||||
# @param button_link text
|
# @param button_link text
|
||||||
# @param content textarea
|
# @param content textarea
|
||||||
# @param embedded toggle
|
# @param embedded toggle
|
||||||
# @param variant select [introduction, promotion]
|
# @param variant select {{ Pajamas::BannerComponent::VARIANT_OPTIONS }}
|
||||||
def default(
|
def default(
|
||||||
button_text: "Learn more",
|
button_text: "Learn more",
|
||||||
button_link: "https://about.gitlab.com/",
|
button_link: "https://about.gitlab.com/",
|
||||||
|
|
|
@ -5,10 +5,10 @@ module Pajamas
|
||||||
# ----
|
# ----
|
||||||
# See its design reference [here](https://design.gitlab.com/components/banner).
|
# See its design reference [here](https://design.gitlab.com/components/banner).
|
||||||
#
|
#
|
||||||
# @param category select [primary, secondary, tertiary]
|
# @param category select {{ Pajamas::ButtonComponent::CATEGORY_OPTIONS }}
|
||||||
# @param variant select [default, confirm, danger, dashed, link, reset]
|
# @param variant select {{ Pajamas::ButtonComponent::VARIANT_OPTIONS }}
|
||||||
# @param size select [small, medium]
|
# @param size select {{ Pajamas::ButtonComponent::SIZE_OPTIONS }}
|
||||||
# @param type select [button, reset, submit]
|
# @param type select {{ Pajamas::ButtonComponent::TYPE_OPTIONS }}
|
||||||
# @param disabled toggle
|
# @param disabled toggle
|
||||||
# @param loading toggle
|
# @param loading toggle
|
||||||
# @param block toggle
|
# @param block toggle
|
||||||
|
|
|
@ -7,8 +7,8 @@ module Pajamas
|
||||||
#
|
#
|
||||||
# See its design reference [here](https://design.gitlab.com/components/progress-bar).
|
# See its design reference [here](https://design.gitlab.com/components/progress-bar).
|
||||||
#
|
#
|
||||||
# @param value number
|
# @param value range { min: 0, max: 100, step: 1 }
|
||||||
# @param variant select [primary, success]
|
# @param variant select {{ Pajamas::ProgressComponent::VARIANT_OPTIONS }}
|
||||||
def default(value: 50, variant: :primary)
|
def default(value: 50, variant: :primary)
|
||||||
render Pajamas::ProgressComponent.new(value: value, variant: variant)
|
render Pajamas::ProgressComponent.new(value: value, variant: variant)
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,7 +7,7 @@ module Pajamas
|
||||||
#
|
#
|
||||||
# @param inline toggle
|
# @param inline toggle
|
||||||
# @param label text
|
# @param label text
|
||||||
# @param size select [[small, sm], [medium, md], [large, lg], [extra large, xl]]
|
# @param size select {{ Pajamas::SpinnerComponent::SIZE_OPTIONS }}
|
||||||
def default(inline: false, label: "Loading", size: :md)
|
def default(inline: false, label: "Loading", size: :md)
|
||||||
render Pajamas::SpinnerComponent.new(
|
render Pajamas::SpinnerComponent.new(
|
||||||
inline: inline,
|
inline: inline,
|
||||||
|
@ -18,7 +18,7 @@ module Pajamas
|
||||||
|
|
||||||
# Use a light spinner on dark backgrounds.
|
# Use a light spinner on dark backgrounds.
|
||||||
#
|
#
|
||||||
# @display bg_color "#222"
|
# @display bg_dark true
|
||||||
def light
|
def light
|
||||||
render(Pajamas::SpinnerComponent.new(color: :light))
|
render(Pajamas::SpinnerComponent.new(color: :light))
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,7 +7,15 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model d
|
||||||
|
|
||||||
it { is_expected.to be_a Gitlab::Database::SharedModel }
|
it { is_expected.to be_a Gitlab::Database::SharedModel }
|
||||||
|
|
||||||
it { expect(described_class::TIMEOUT_EXCEPTIONS).to match_array [ActiveRecord::StatementTimeout, ActiveRecord::ConnectionTimeoutError, ActiveRecord::AdapterTimeout, ActiveRecord::LockWaitTimeout] }
|
specify do
|
||||||
|
expect(described_class::TIMEOUT_EXCEPTIONS).to contain_exactly(
|
||||||
|
ActiveRecord::StatementTimeout,
|
||||||
|
ActiveRecord::ConnectionTimeoutError,
|
||||||
|
ActiveRecord::AdapterTimeout,
|
||||||
|
ActiveRecord::LockWaitTimeout,
|
||||||
|
ActiveRecord::QueryCanceled
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
describe 'associations' do
|
describe 'associations' do
|
||||||
it { is_expected.to belong_to(:batched_migration).with_foreign_key(:batched_background_migration_id) }
|
it { is_expected.to belong_to(:batched_migration).with_foreign_key(:batched_background_migration_id) }
|
||||||
|
@ -279,14 +287,6 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model d
|
||||||
let(:exception) { ActiveRecord::QueryCanceled.new }
|
let(:exception) { ActiveRecord::QueryCanceled.new }
|
||||||
|
|
||||||
it { expect(subject).to be_truthy }
|
it { expect(subject).to be_truthy }
|
||||||
|
|
||||||
context 'when split_background_migration_on_query_canceled feature flag is disabled' do
|
|
||||||
before do
|
|
||||||
stub_feature_flags(split_background_migration_on_query_canceled: false)
|
|
||||||
end
|
|
||||||
|
|
||||||
it { expect(subject).to be_falsey }
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when is not a timeout exception' do
|
context 'when is not a timeout exception' do
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
RSpec.describe Subquery do
|
||||||
|
let_it_be(:projects) { create_list :project, 3 }
|
||||||
|
let_it_be(:project_ids) { projects.map(&:id) }
|
||||||
|
let(:relation) { Project.where(id: projects) }
|
||||||
|
|
||||||
|
subject { relation.subquery(:id) }
|
||||||
|
|
||||||
|
shared_examples 'subquery as array values' do
|
||||||
|
specify { is_expected.to match_array project_ids }
|
||||||
|
specify { expect { subject }.not_to make_queries }
|
||||||
|
end
|
||||||
|
|
||||||
|
shared_examples 'subquery as relation' do
|
||||||
|
it { is_expected.to be_a ActiveRecord::Relation }
|
||||||
|
specify { expect { subject.load }.to make_queries }
|
||||||
|
end
|
||||||
|
|
||||||
|
shared_context 'when array size exceeds max_limit' do
|
||||||
|
subject { relation.subquery(:id, max_limit: 1) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when relation is not loaded' do
|
||||||
|
it_behaves_like 'subquery as relation'
|
||||||
|
|
||||||
|
context 'when array size exceeds max_limit' do
|
||||||
|
include_context 'when array size exceeds max_limit'
|
||||||
|
|
||||||
|
it_behaves_like 'subquery as relation'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when relation is loaded' do
|
||||||
|
before do
|
||||||
|
relation.load
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'subquery as array values'
|
||||||
|
|
||||||
|
context 'when array size exceeds max_limit' do
|
||||||
|
include_context 'when array size exceeds max_limit'
|
||||||
|
|
||||||
|
it_behaves_like 'subquery as relation'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with a select' do
|
||||||
|
let(:relation) { Project.where(id: projects).select(:id) }
|
||||||
|
|
||||||
|
it_behaves_like 'subquery as array values'
|
||||||
|
|
||||||
|
context 'and querying with an unloaded column' do
|
||||||
|
subject { relation.subquery(:namespace_id) }
|
||||||
|
|
||||||
|
it { expect { subject }.to raise_error(ActiveModel::MissingAttributeError) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -28,7 +28,7 @@ RSpec.describe Preloaders::UserMaxAccessLevelInProjectsPreloader do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#execute', :request_store do
|
shared_examples '#execute' do
|
||||||
let(:projects_arg) { projects }
|
let(:projects_arg) { projects }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
|
@ -58,4 +58,16 @@ RSpec.describe Preloaders::UserMaxAccessLevelInProjectsPreloader do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#execute', :request_store do
|
||||||
|
include_examples '#execute'
|
||||||
|
|
||||||
|
context 'when projects_preloader_fix is disabled' do
|
||||||
|
before do
|
||||||
|
stub_feature_flags(projects_preloader_fix: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
include_examples '#execute'
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1353,7 +1353,7 @@ RSpec.describe Project, factory_default: :keep do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#open_issues_count', :aggregate_failures do
|
describe '#open_issues_count' do
|
||||||
let(:project) { build(:project) }
|
let(:project) { build(:project) }
|
||||||
|
|
||||||
it 'provides the issue count' do
|
it 'provides the issue count' do
|
||||||
|
|
|
@ -207,7 +207,8 @@ RSpec.describe API::Projects do
|
||||||
let(:current_user) { user }
|
let(:current_user) { user }
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'includes container_registry_access_level', :aggregate_failures do
|
shared_examples 'includes container_registry_access_level', :aggregate_failures do
|
||||||
|
it do
|
||||||
project.project_feature.update!(container_registry_access_level: ProjectFeature::DISABLED)
|
project.project_feature.update!(container_registry_access_level: ProjectFeature::DISABLED)
|
||||||
|
|
||||||
get api('/projects', user)
|
get api('/projects', user)
|
||||||
|
@ -218,6 +219,17 @@ RSpec.describe API::Projects do
|
||||||
expect(project_response['container_registry_access_level']).to eq('disabled')
|
expect(project_response['container_registry_access_level']).to eq('disabled')
|
||||||
expect(project_response['container_registry_enabled']).to eq(false)
|
expect(project_response['container_registry_enabled']).to eq(false)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
include_examples 'includes container_registry_access_level'
|
||||||
|
|
||||||
|
context 'when projects_preloader_fix is disabled' do
|
||||||
|
before do
|
||||||
|
stub_feature_flags(projects_preloader_fix: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
include_examples 'includes container_registry_access_level'
|
||||||
|
end
|
||||||
|
|
||||||
it 'includes releases_access_level', :aggregate_failures do
|
it 'includes releases_access_level', :aggregate_failures do
|
||||||
project.project_feature.update!(releases_access_level: ProjectFeature::DISABLED)
|
project.project_feature.update!(releases_access_level: ProjectFeature::DISABLED)
|
||||||
|
|
|
@ -292,16 +292,6 @@ RSpec.describe IncidentManagement::TimelineEvents::CreateService do
|
||||||
let(:expected_action) { 'severity' }
|
let(:expected_action) { 'severity' }
|
||||||
|
|
||||||
it_behaves_like 'successfully created timeline event'
|
it_behaves_like 'successfully created timeline event'
|
||||||
|
|
||||||
context 'when feature flag is disabled' do
|
|
||||||
before do
|
|
||||||
stub_feature_flags(incident_timeline_events_for_severity: false)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'does not create new timeline event' do
|
|
||||||
expect { execute }.not_to change { incident.incident_management_timeline_events.count }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '.change_labels' do
|
describe '.change_labels' do
|
||||||
|
|
|
@ -82,39 +82,5 @@ RSpec.describe Projects::PostCreationWorker do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'Incident timeline event tags' do
|
|
||||||
context 'when project is nil' do
|
|
||||||
let(:job_args) { [nil] }
|
|
||||||
|
|
||||||
it 'does not create event tags' do
|
|
||||||
expect { subject }.not_to change { IncidentManagement::TimelineEventTag.count }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when project is created', :aggregate_failures do
|
|
||||||
it 'creates tags for the project' do
|
|
||||||
expect { subject }.to change { IncidentManagement::TimelineEventTag.count }.by(2)
|
|
||||||
|
|
||||||
expect(project.incident_management_timeline_event_tags.pluck_names).to match_array(
|
|
||||||
[
|
|
||||||
::IncidentManagement::TimelineEventTag::START_TIME_TAG_NAME,
|
|
||||||
::IncidentManagement::TimelineEventTag::END_TIME_TAG_NAME
|
|
||||||
]
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'raises error if record creation fails' do
|
|
||||||
allow_next_instance_of(IncidentManagement::TimelineEventTag) do |tag|
|
|
||||||
allow(tag).to receive(:valid?).and_return(false)
|
|
||||||
end
|
|
||||||
|
|
||||||
expect(Gitlab::ErrorTracking).to receive(:track_exception).with(an_instance_of(ActiveRecord::RecordInvalid), include(extra: { project_id: a_kind_of(Integer) })).twice
|
|
||||||
subject
|
|
||||||
|
|
||||||
expect(project.incident_management_timeline_event_tags).to be_empty
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue