Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-11-09 06:11:32 +00:00
parent 6faeb44a01
commit 7b29a4f84e
41 changed files with 287 additions and 140 deletions

View File

@ -17,10 +17,10 @@ module Pajamas
@avatar_options = avatar_options
end
private
SIZE_OPTIONS = [16, 24, 32, 48, 64, 96].freeze
private
def avatar_classes
classes = ["gl-avatar", "gl-avatar-s#{@size}", @class]
classes.push("gl-avatar-circle") if @record.is_a?(User)

View File

@ -22,11 +22,11 @@ module Pajamas
@html_options = html_options
end
private
SIZE_OPTIONS = [:sm, :md, :lg].freeze
VARIANT_OPTIONS = [:muted, :neutral, :info, :success, :warning, :danger].freeze
private
delegate :sprite_icon, to: :helpers
def badge_classes

View File

@ -23,13 +23,15 @@ module Pajamas
@button_text = button_text
@button_link = button_link
@embedded = embedded
@variant = variant.to_sym
@variant = filter_attribute(variant.to_sym, VARIANT_OPTIONS, default: :promotion)
@svg_path = svg_path.to_s
@banner_options = banner_options
@button_options = button_options
@close_options = close_options
end
VARIANT_OPTIONS = [:introduction, :promotion].freeze
private
def banner_class

View File

@ -14,15 +14,15 @@ module Pajamas
@html_options = html_options
end
COLOR_OPTIONS = [:light, :dark].freeze
SIZE_OPTIONS = [:sm, :md, :lg, :xl].freeze
private
def spinner_class
["gl-spinner", "gl-spinner-#{@size}", "gl-spinner-#{@color} gl-vertical-align-text-bottom!"]
end
COLOR_OPTIONS = [:light, :dark].freeze
SIZE_OPTIONS = [:sm, :md, :lg, :xl].freeze
def html_options
options = format_options(options: @html_options, css_classes: "gl-spinner-container")
options[:role] = "status"

View File

@ -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

View File

@ -7,9 +7,11 @@ module Preloaders
def initialize(projects, user)
@projects = if projects.is_a?(Array)
Project.where(id: projects)
else
elsif Feature.enabled?(:projects_preloader_fix)
# Push projects base query in to a sub-select to avoid
# table name clashes. Performs better than aliasing.
Project.where(id: projects.subquery(:id))
else
Project.where(id: projects.reselect(:id))
end

View File

@ -39,6 +39,7 @@ class Project < ApplicationRecord
include BulkUsersByEmailLoad
include RunnerTokenExpirationInterval
include BlocksUnsafeSerialization
include Subquery
extend Gitlab::Cache::RequestCache
extend Gitlab::Utils::Override

View File

@ -50,8 +50,6 @@ module IncidentManagement
end
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]
note = "@#{user.username} changed the incident severity to **#{severity_label}**"
occurred_at = incident.updated_at

View File

@ -1,5 +1,14 @@
%head
= stylesheet_link_tag "application"
= stylesheet_link_tag "application_utilities"
%body{ style: "background-color: #{params.dig(:lookbook, :display, :bg_color) || 'white'}" }
.container.gl-mt-6= yield
- if params[:lookbook][:display][:theme] == 'light'
= stylesheet_link_tag "application"
= stylesheet_link_tag "application_utilities"
- else
= 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

View File

@ -17,7 +17,6 @@ module Projects
return unless project
create_prometheus_integration(project)
create_incident_management_timeline_event_tags(project)
end
private

View File

@ -51,6 +51,10 @@ Rails.application.configure do
config.autoload_paths.push("#{config.root}/spec/components/previews")
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.
# Checks for improperly declared sprockets dependencies.

View File

@ -1,8 +1,8 @@
---
name: incident_timeline_events_for_severity
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/100954
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/378408
name: projects_preloader_fix
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96108
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/378858
milestone: '15.6'
type: development
group: group::respond
group: group::workspace
default_enabled: false

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1 @@
951ad9faf483d58778cd831a0ac949473d6eeb753322754eff3f02756d757583

View File

@ -0,0 +1 @@
2185444f733eec25a2741764619516eecb1d2c6e3e4ec3b3ed5b72bfd9c4db46

View File

@ -0,0 +1 @@
b8438bebe77ae835b754431d8d67c306714205bef11826a15d4c84d7b67a3581

View File

@ -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_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_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 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 work_item_types_namespace_id_and_name_unique ON work_item_types USING btree (namespace_id, btrim(lower(name)));

View File

@ -76,13 +76,7 @@ The comment is shown on the incident timeline as a timeline event.
### 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.
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.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/375280) in GitLab 15.6.
A new timeline event is created when someone [changes the severity](incidents.md#change-severity)
of an incident.

View File

@ -146,7 +146,7 @@ To disable analyzer rules:
1. Create a custom ruleset file named `sast-ruleset.toml` in the `.gitlab` directory, if
one doesn't already exist.
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:
- 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:
@ -163,6 +163,12 @@ the `kics` analyzer by matching the `type` and `value` of identifiers:
[kics.ruleset.identifier]
type = "kics_id"
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

View File

@ -60,6 +60,8 @@ module API
super
end
def self.postload_relation(projects_relation, options = {}) end
private
alias_method :project, :object

View File

@ -25,23 +25,41 @@ module API
# rubocop: disable CodeReuse/ActiveRecord
def self.preload_relation(projects_relation, options = {})
relation = super(projects_relation, options)
# use reselect to override the existing select and
# prevent an error `subquery has too many columns`
project_ids = relation.reselect('projects.id')
namespace_ids = relation.reselect(:namespace_id)
if ::Feature.enabled?(:projects_preloader_fix)
super(projects_relation, options)
else
relation = super(projects_relation, options)
# use reselect to override the existing select and
# prevent an error `subquery has too many columns`
project_ids = relation.reselect('projects.id')
namespace_ids = relation.reselect(:namespace_id)
options[:project_members] = options[:current_user]
.project_members
.where(source_id: project_ids)
.preload(:source, user: [notification_settings: :source])
options[:group_members] = options[:current_user]
.group_members
.where(source_id: namespace_ids)
.preload(:source, user: [notification_settings: :source])
relation
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: project_ids)
.where(source_id: projects_relation.subquery(:id))
.preload(:source, user: [notification_settings: :source])
options[:group_members] = options[:current_user]
.group_members
.where(source_id: namespace_ids)
.where(source_id: projects_relation.subquery(:namespace_id))
.preload(:source, user: [notification_settings: :source])
relation
end
# rubocop: enable CodeReuse/ActiveRecord
end

View File

@ -10,6 +10,8 @@ module API
execute_batch_counting(projects_relation)
postload_relation(projects_relation, options)
preload_repository_cache(projects_relation)
Preloaders::UserMaxAccessLevelInProjectsPreloader.new(projects_relation, options[:current_user]).execute if options[:current_user]

View File

@ -14,7 +14,8 @@ module Gitlab
MAX_ATTEMPTS = 3
STUCK_JOBS_TIMEOUT = 1.hour.freeze
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
has_many :batched_job_transition_logs, foreign_key: :batched_background_migration_job_id
@ -112,7 +113,10 @@ module Gitlab
end
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
def split_and_retry!
@ -161,15 +165,6 @@ module Gitlab
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

View File

@ -41,11 +41,11 @@ gitlab:
migrations:
resources:
requests:
cpu: 200m
memory: 500Mi
limits:
cpu: 400m
memory: 1000Mi
memory: 920Mi
limits:
cpu: 600m
memory: 1100Mi
gitlab-shell:
resources:
requests:

View File

@ -4,7 +4,7 @@ module Pajamas
# @param title text
# @param body text
# @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)
render(Pajamas::AlertComponent.new(
title: title,

View File

@ -9,17 +9,17 @@ module Pajamas
end
# 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)
render(Pajamas::AvatarComponent.new(User.first, size: size))
end
# @param size select [16, 24, 32, 48, 64, 96]
# @param size select {{ Pajamas::AvatarComponent::SIZE_OPTIONS }}
def project(size: 64)
render(Pajamas::AvatarComponent.new(Project.first, size: size))
end
# @param size select [16, 24, 32, 48, 64, 96]
# @param size select {{ Pajamas::AvatarComponent::SIZE_OPTIONS }}
def group(size: 64)
render(Pajamas::AvatarComponent.new(Group.first, size: size))
end

View File

@ -10,9 +10,9 @@ module Pajamas
# @param icon select [~, star-o, issue-closed, tanuki]
# @param icon_only toggle
# @param href url
# @param size select [sm, md, lg]
# @param size select {{ Pajamas::BadgeComponent::SIZE_OPTIONS }}
# @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)
render Pajamas::BadgeComponent.new(
text,

View File

@ -9,7 +9,7 @@ module Pajamas
# @param button_link text
# @param content textarea
# @param embedded toggle
# @param variant select [introduction, promotion]
# @param variant select {{ Pajamas::BannerComponent::VARIANT_OPTIONS }}
def default(
button_text: "Learn more",
button_link: "https://about.gitlab.com/",

View File

@ -5,10 +5,10 @@ module Pajamas
# ----
# See its design reference [here](https://design.gitlab.com/components/banner).
#
# @param category select [primary, secondary, tertiary]
# @param variant select [default, confirm, danger, dashed, link, reset]
# @param size select [small, medium]
# @param type select [button, reset, submit]
# @param category select {{ Pajamas::ButtonComponent::CATEGORY_OPTIONS }}
# @param variant select {{ Pajamas::ButtonComponent::VARIANT_OPTIONS }}
# @param size select {{ Pajamas::ButtonComponent::SIZE_OPTIONS }}
# @param type select {{ Pajamas::ButtonComponent::TYPE_OPTIONS }}
# @param disabled toggle
# @param loading toggle
# @param block toggle

View File

@ -7,8 +7,8 @@ module Pajamas
#
# See its design reference [here](https://design.gitlab.com/components/progress-bar).
#
# @param value number
# @param variant select [primary, success]
# @param value range { min: 0, max: 100, step: 1 }
# @param variant select {{ Pajamas::ProgressComponent::VARIANT_OPTIONS }}
def default(value: 50, variant: :primary)
render Pajamas::ProgressComponent.new(value: value, variant: variant)
end

View File

@ -7,7 +7,7 @@ module Pajamas
#
# @param inline toggle
# @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)
render Pajamas::SpinnerComponent.new(
inline: inline,
@ -18,7 +18,7 @@ module Pajamas
# Use a light spinner on dark backgrounds.
#
# @display bg_color "#222"
# @display bg_dark true
def light
render(Pajamas::SpinnerComponent.new(color: :light))
end

View File

@ -7,7 +7,15 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model d
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
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 }
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
context 'when is not a timeout exception' do

View File

@ -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

View File

@ -28,7 +28,7 @@ RSpec.describe Preloaders::UserMaxAccessLevelInProjectsPreloader do
end
end
describe '#execute', :request_store do
shared_examples '#execute' do
let(:projects_arg) { projects }
before do
@ -58,4 +58,16 @@ RSpec.describe Preloaders::UserMaxAccessLevelInProjectsPreloader do
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

View File

@ -1353,7 +1353,7 @@ RSpec.describe Project, factory_default: :keep do
end
end
describe '#open_issues_count', :aggregate_failures do
describe '#open_issues_count' do
let(:project) { build(:project) }
it 'provides the issue count' do

View File

@ -207,16 +207,28 @@ RSpec.describe API::Projects do
let(:current_user) { user }
end
it 'includes container_registry_access_level', :aggregate_failures do
project.project_feature.update!(container_registry_access_level: ProjectFeature::DISABLED)
shared_examples 'includes container_registry_access_level', :aggregate_failures do
it do
project.project_feature.update!(container_registry_access_level: ProjectFeature::DISABLED)
get api('/projects', user)
project_response = json_response.find { |p| p['id'] == project.id }
get api('/projects', user)
project_response = json_response.find { |p| p['id'] == project.id }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to be_an Array
expect(project_response['container_registry_access_level']).to eq('disabled')
expect(project_response['container_registry_enabled']).to eq(false)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to be_an Array
expect(project_response['container_registry_access_level']).to eq('disabled')
expect(project_response['container_registry_enabled']).to eq(false)
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

View File

@ -292,16 +292,6 @@ RSpec.describe IncidentManagement::TimelineEvents::CreateService do
let(:expected_action) { 'severity' }
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
describe '.change_labels' do

View File

@ -82,39 +82,5 @@ RSpec.describe Projects::PostCreationWorker do
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