Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2023-07-14 03:09:17 +00:00
parent 804348d39b
commit c69e4aa48c
82 changed files with 415 additions and 476 deletions

View File

@ -317,7 +317,6 @@ Layout/LineLength:
- 'app/models/concerns/packages/debian/distribution.rb'
- 'app/models/concerns/packages/debian/distribution_key.rb'
- 'app/models/concerns/partitioned_table.rb'
- 'app/models/concerns/protected_ref.rb'
- 'app/models/concerns/redis_cacheable.rb'
- 'app/models/concerns/restricted_signup.rb'
- 'app/models/concerns/shardable.rb'

View File

@ -184,7 +184,7 @@ gem 'elasticsearch-rails', '~> 7.2', require: 'elasticsearch/rails/instrumentati
gem 'elasticsearch-api', '7.13.3'
gem 'aws-sdk-core', '~> 3.178.0'
gem 'aws-sdk-cloudformation', '~> 1'
gem 'aws-sdk-s3', '~> 1.129.0'
gem 'aws-sdk-s3', '~> 1.130.0'
gem 'faraday_middleware-aws-sigv4', '~>0.3.0'
gem 'typhoeus', '~> 1.4.0' # Used with Elasticsearch to support http keep-alive connections

View File

@ -39,7 +39,7 @@
{"name":"aws-sdk-cloudformation","version":"1.41.0","platform":"ruby","checksum":"31e47539719734413671edf9b1a31f8673fbf9688549f50c41affabbcb1c6b26"},
{"name":"aws-sdk-core","version":"3.178.0","platform":"ruby","checksum":"192485a032536ff8c8eb037f1204b432129a612f4de13e36c0d2cf0dec8165cb"},
{"name":"aws-sdk-kms","version":"1.64.0","platform":"ruby","checksum":"40de596c95047bfc6e1aacea24f3df6241aa716b6f7ce08ac4c5f7e3120395ad"},
{"name":"aws-sdk-s3","version":"1.129.0","platform":"ruby","checksum":"82b8eab53d22754e5855dbec3e7a9a53c348de2bbf202774b4483f9b06cb0f1a"},
{"name":"aws-sdk-s3","version":"1.130.0","platform":"ruby","checksum":"80ac391ede15dcc62f1ada2fec12719a22148cf64ef76e5ec929558bb936c72a"},
{"name":"aws-sigv4","version":"1.6.0","platform":"ruby","checksum":"ca9e6a15cd424f1f32b524b9760995331459bc22e67d3daad4fcf0c0084b087d"},
{"name":"axe-core-api","version":"4.6.0","platform":"ruby","checksum":"1b0ddec3353f108dc10363baf2282f43a5ff7f13d4e25f99071294e78f8a6c62"},
{"name":"axe-core-rspec","version":"4.6.0","platform":"ruby","checksum":"11c25bc9dd388c137ba4e5e63d64d20092bf22c884d8ffc829a22acfbacd747f"},

View File

@ -262,7 +262,7 @@ GEM
aws-sdk-kms (1.64.0)
aws-sdk-core (~> 3, >= 3.165.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.129.0)
aws-sdk-s3 (1.130.0)
aws-sdk-core (~> 3, >= 3.177.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.6)
@ -1740,7 +1740,7 @@ DEPENDENCIES
awesome_print
aws-sdk-cloudformation (~> 1)
aws-sdk-core (~> 3.178.0)
aws-sdk-s3 (~> 1.129.0)
aws-sdk-s3 (~> 1.130.0)
axe-core-rspec
babosa (~> 2.0)
base32 (~> 0.3.0)

View File

@ -8,7 +8,7 @@ $search-input-field-x-min-width: 200px;
min-height: $header-height;
border: 0;
position: fixed;
top: $calc-application-bars-height;
top: $calc-system-headers-height;
left: 0;
right: 0;
border-radius: 0;
@ -322,7 +322,7 @@ $search-input-field-x-min-width: 200px;
left: var(--application-bar-left);
position: fixed;
right: var(--application-bar-right);
top: $calc-application-bars-height;
top: $calc-system-headers-height;
width: auto;
z-index: $top-bar-z-index;

View File

@ -36,7 +36,7 @@ body {
}
.layout-page {
padding-top: calc(#{$header-height} + #{$calc-application-bars-height});
padding-top: $calc-application-bars-height;
padding-bottom: $calc-application-footer-height;
}

View File

@ -317,7 +317,7 @@
.right-sidebar {
&:not(.right-sidebar-merge-requests) {
@include right-sidebar;
top: calc(#{$header-height} + #{$calc-application-bars-height});
top: $calc-application-bars-height;
@include media-breakpoint-down(md) {
z-index: 251;
@ -327,7 +327,7 @@
&.right-sidebar-merge-requests {
@include media-breakpoint-down(md) {
@include right-sidebar;
top: calc(#{$header-height} + #{$calc-application-bars-height});
top: $calc-application-bars-height;
z-index: 251;
}

View File

@ -23,7 +23,7 @@ $super-sidebar-transition-hint-duration: $super-sidebar-transition-duration / 4;
}
.super-sidebar-skip-to {
top: calc(#{$header-height} + #{$calc-application-bars-height});
top: $calc-application-bars-height;
width: calc(#{$super-sidebar-width} - #{$gl-spacing-scale-5});
z-index: $super-sidebar-skip-to-z-index;
}
@ -32,7 +32,7 @@ $super-sidebar-transition-hint-duration: $super-sidebar-transition-duration / 4;
display: flex;
flex-direction: column;
position: fixed;
top: calc(#{$header-height} + #{$calc-application-bars-height});
top: $calc-application-bars-height;
bottom: $calc-application-footer-height;
left: 0;
background-color: var(--gray-10, $gray-10);

View File

@ -502,8 +502,9 @@ $pages-group-name-color: #4c4e54;
/*
* Calculated heights
*/
$calc-application-bars-height: calc(var(--system-header-height) + var(--performance-bar-height));
$calc-application-header-height: calc(#{$header-height} + #{$calc-application-bars-height} + var(--top-bar-height));
$calc-system-headers-height: calc(var(--system-header-height) + var(--performance-bar-height));
$calc-application-bars-height: calc(#{$header-height} + #{$calc-system-headers-height});
$calc-application-header-height: calc(#{$calc-application-bars-height} + var(--top-bar-height));
$calc-application-footer-height: var(--system-footer-height);
$calc-application-viewport-height: calc(100vh - #{$calc-application-header-height} - #{$calc-application-footer-height});

View File

@ -42,7 +42,7 @@
// Override Bootstrap class with offset for system-header and
// performance bar when present
.fixed-top {
top: $calc-application-bars-height;
top: $calc-system-headers-height;
}
.gl-children-ml-sm-3 > * {

View File

@ -61,6 +61,7 @@ class EventsFinder
def by_current_user_access(events)
events.merge(Project.public_or_visible_to_user(current_user))
.joins(:project)
.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/417462")
end
# rubocop: enable CodeReuse/ActiveRecord

View File

@ -5,6 +5,8 @@ module Issuables
def filter(issuables)
filtered = by_assignee(issuables)
filtered = by_assignee_union(filtered)
# Cross Joins Fails tests in bin/rspec spec/requests/api/graphql/boards/board_list_issues_query_spec.rb
filtered = filtered.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/417462")
by_negated_assignee(filtered)
end

View File

@ -90,8 +90,10 @@ class MembersFinder
# enumerate the columns here since we are enumerating them in the union and want to be immune to
# column caching issues when adding/removing columns
Member.select(*Member.column_names)
members = Member.select(*Member.column_names)
.includes(:user).from([Arel.sql("(#{sql}) AS #{Member.table_name}")]) # rubocop: disable CodeReuse/ActiveRecord
# The left join with the table users in the method distinct_on needs to be resolved
members.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/417456")
end
def distinct_on(union)

View File

@ -73,6 +73,7 @@ class MergeRequestsFinder < IssuableFinder
items = by_deployments(items)
items = by_reviewer(items)
items = by_source_project_id(items)
items = items.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/417462")
by_approved(items)
end

View File

@ -19,7 +19,7 @@ module IssueAvailableFeatures
end
included do
scope :with_feature, ->(feature) { where(issue_type: available_features_for_issue_types[feature]) }
scope :with_feature, ->(feature) { with_issue_type(available_features_for_issue_types[feature]) }
end
def issue_type_supports?(feature)

View File

@ -1,59 +0,0 @@
# frozen_string_literal: true
# TODO: Remove with https://gitlab.com/gitlab-org/gitlab/-/issues/402699
module Issues
module ForbidIssueTypeColumnUsage
extend ActiveSupport::Concern
ForbiddenColumnUsed = Class.new(StandardError)
included do
WorkItems::Type.base_types.each do |base_type, _value|
define_method "#{base_type}?".to_sym do
error_message = <<~ERROR
`#{model_name.element}.#{base_type}?` uses the `issue_type` column underneath. As we want to remove the column,
its usage is forbidden. You should use the `work_item_types` table instead.
# Before
#{model_name.element}.#{base_type}? => true
# After
#{model_name.element}.work_item_type.#{base_type}? => true
More details in https://gitlab.com/groups/gitlab-org/-/epics/10529
ERROR
raise ForbiddenColumnUsed, error_message
end
define_singleton_method base_type.to_sym do
error = ForbiddenColumnUsed.new(
<<~ERROR
`#{name}.#{base_type}` uses the `issue_type` column underneath. As we want to remove the column,
its usage is forbidden. You should use the `work_item_types` table instead.
# Before
#{name}.#{base_type}
# After
#{name}.with_issue_type(:#{base_type})
More details in https://gitlab.com/groups/gitlab-org/-/epics/10529
ERROR
)
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(
error,
method_name: "#{name}.#{base_type}"
)
with_issue_type(base_type.to_sym)
end
end
end
end
end

View File

@ -51,6 +51,7 @@ module Milestoneish
def issue_participants_visible_by_user(user)
User.joins(:issue_assignees)
.where('issue_assignees.issue_id' => issues_visible_to_user(user).select(:id))
.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/417457")
.distinct
end

View File

@ -32,7 +32,12 @@ module ProtectedRef
# to fail.
has_many :"#{type}_access_levels", inverse_of: self.model_name.singular
validates :"#{type}_access_levels", length: { is: 1, message: "are restricted to a single instance per #{self.model_name.human}." }, unless: -> { allow_multiple?(type) }
validates :"#{type}_access_levels",
length: {
is: 1,
message: "are restricted to a single instance per #{self.model_name.human}."
},
unless: -> { allow_multiple?(type) }
accepts_nested_attributes_for :"#{type}_access_levels", allow_destroy: true
end

View File

@ -38,7 +38,14 @@ module ProtectedRefAccess
included do
scope :maintainer, -> { where(access_level: Gitlab::Access::MAINTAINER) }
scope :developer, -> { where(access_level: Gitlab::Access::DEVELOPER) }
scope :for_role, -> { non_role_types.present? ? where.missing(*non_role_types) : all }
scope :for_role, -> {
if non_role_types.present?
where.missing(*non_role_types)
.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/417457")
else
all
end
}
protected_ref_fk = "#{module_parent.model_name.singular}_id"
validates :access_level,

View File

@ -510,7 +510,9 @@ class Group < Namespace
members_with_parents(only_active_users: false)
end
members_from_hiearchy.all_owners.left_outer_joins(:user).merge(User.without_project_bot)
members_from_hiearchy.all_owners.left_outer_joins(:user)
.merge(User.without_project_bot)
.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/417455")
end
def ldap_synced?
@ -694,7 +696,7 @@ class Group < Namespace
.where(id: direct_and_indirect_members_with_inactive.select(:user_id))
.reorder(nil),
project_users_with_descendants
])
]).allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/417455") # failed in spec/tasks/gitlab/user_management_rake_spec.rb
end
def users_count
@ -707,6 +709,7 @@ class Group < Namespace
User
.joins(projects: :group)
.where(namespaces: { id: self_and_descendants.select(:id) })
.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/417455")
end
# Return the highest access level for a user
@ -973,12 +976,14 @@ class Group < Namespace
end
def max_member_access(user_ids)
Gitlab::SafeRequestLoader.execute(
resource_key: max_member_access_for_resource_key(User),
resource_ids: user_ids,
default_value: Gitlab::Access::NO_ACCESS
) do |user_ids|
members_with_parents.where(user_id: user_ids).group(:user_id).maximum(:access_level)
::Gitlab::Database.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/417455") do
Gitlab::SafeRequestLoader.execute(
resource_key: max_member_access_for_resource_key(User),
resource_ids: user_ids,
default_value: Gitlab::Access::NO_ACCESS
) do |user_ids|
members_with_parents.where(user_id: user_ids).group(:user_id).maximum(:access_level)
end
end
end

View File

@ -56,6 +56,8 @@ class Issue < ApplicationRecord
# This default came from the enum `issue_type` column. Defined as default in the DB
DEFAULT_ISSUE_TYPE = :issue
ignore_column :issue_type, remove_with: '16.4', remove_after: '2023-08-22'
belongs_to :project
belongs_to :namespace, inverse_of: :issues
@ -133,12 +135,6 @@ class Issue < ApplicationRecord
validate :allowed_work_item_type_change, on: :update, if: :work_item_type_id_changed?
validate :due_date_after_start_date
validate :parent_link_confidentiality
# using a custom validation since we are overwriting the `issue_type` method to use the work_item_types table
validate :issue_type_attribute_present
enum issue_type: WorkItems::Type.base_types
# TODO: Remove with https://gitlab.com/gitlab-org/gitlab/-/issues/402699
include ::Issues::ForbidIssueTypeColumnUsage
alias_method :issuing_parent, :project
alias_attribute :issuing_parent_id, :project_id
@ -254,7 +250,6 @@ class Issue < ApplicationRecord
scope :with_projects_matching_search_data, -> { where('issue_search_data.project_id = issues.project_id') }
before_validation :ensure_namespace_id, :ensure_work_item_type
before_save :check_issue_type_in_sync!
after_save :ensure_metrics!, unless: :importing?
after_commit :expire_etag_cache, unless: :importing?
@ -760,40 +755,6 @@ class Issue < ApplicationRecord
private
def check_issue_type_in_sync!
# We might have existing records out of sync, so we need to skip this check unless the value is changed
# so those records can still be updated until we fix them and remove the issue_type column
# https://gitlab.com/gitlab-org/gitlab/-/work_items/403158
return unless (changes.keys & %w[issue_type work_item_type_id]).any?
# Do not replace the use of attributes with `issue_type` here
if attributes['issue_type'] != work_item_type.base_type
error = IssueTypeOutOfSyncError.new(
<<~ERROR
Issue `issue_type` out of sync with `work_item_type_id` column.
`issue_type` must be equal to `work_item.base_type`.
You can assign the correct work_item_type like this for example:
Issue.new(issue_type: :incident, work_item_type: WorkItems::Type.default_by_type(:incident))
More details in https://gitlab.com/gitlab-org/gitlab/-/issues/338005
ERROR
)
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(
error,
issue_type: attributes['issue_type'],
work_item_type_id: work_item_type_id
)
end
end
def issue_type_attribute_present
return if attributes['issue_type'].present?
errors.add(:issue_type, 'Must be present')
end
def due_date_after_start_date
return unless start_date.present? && due_date.present?
@ -854,9 +815,7 @@ class Issue < ApplicationRecord
def ensure_work_item_type
return if work_item_type_id.present? || work_item_type_id_change&.last.present?
# TODO: We should switch to DEFAULT_ISSUE_TYPE here when the issue_type column is dropped
# https://gitlab.com/gitlab-org/gitlab/-/work_items/402700
self.work_item_type = WorkItems::Type.default_by_type(attributes['issue_type'])
self.work_item_type = WorkItems::Type.default_by_type(DEFAULT_ISSUE_TYPE)
end
def allowed_work_item_type_change

View File

@ -66,6 +66,7 @@ class Member < ApplicationRecord
scope :with_invited_user_state, -> do
joins('LEFT JOIN users as invited_user ON invited_user.email = members.invite_email')
.select('members.*', 'invited_user.state as invited_user_state')
.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/417456")
end
scope :in_hierarchy, ->(source) do
@ -174,7 +175,10 @@ class Member < ApplicationRecord
scope :by_access_level, -> (access_level) { active.where(access_level: access_level) }
scope :all_by_access_level, -> (access_level) { where(access_level: access_level) }
scope :preload_user_and_notification_settings, -> { preload(user: :notification_settings) }
scope :preload_user_and_notification_settings, -> do
preload(user: :notification_settings)
.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/417456")
end
scope :with_source_id, ->(source_id) { where(source_id: source_id) }
scope :including_source, -> { includes(:source) }
@ -288,7 +292,9 @@ class Member < ApplicationRecord
class << self
def search(query)
scope = joins(:user).merge(User.search(query, use_minimum_char_limit: false))
scope = joins(:user)
.merge(User.search(query, use_minimum_char_limit: false))
.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/417456")
return scope unless Gitlab::Pagination::Keyset::Order.keyset_aware?(scope)
@ -347,6 +353,7 @@ class Member < ApplicationRecord
def left_join_users
left_outer_joins(:user)
.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/417456")
end
def access_for_user_ids(user_ids)

View File

@ -28,6 +28,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
[
commits_anchor_data,
branches_anchor_data,
terraform_states_anchor_data,
tags_anchor_data,
storage_anchor_data,
releases_anchor_data,
@ -236,6 +237,21 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
)
end
def terraform_states_anchor_data
if project.terraform_states.exists? && can_read_terraform_state?
AnchorData.new(
true,
statistic_icon('terraform') +
n_('%{strong_start}%{terraform_states_count}%{strong_end} Terraform State', '%{strong_start}%{terraform_states_count}%{strong_end} Terraform States', project.terraform_states.count).html_safe % {
terraform_states_count: number_with_delimiter(project.terraform_states.count),
strong_start: '<strong class="project-stat-value">'.html_safe,
strong_end: '</strong>'.html_safe
},
project_terraform_index_path(project)
)
end
end
def tags_anchor_data
AnchorData.new(
true,
@ -488,6 +504,10 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
end
end
def can_read_terraform_state?
current_user && can?(current_user, :read_terraform_state, project)
end
# Avoid including ActionView::Helpers::UrlHelper
def content_tag(...)
ActionController::Base.helpers.content_tag(...)

View File

@ -13,14 +13,17 @@ module Boards
# rubocop: disable CodeReuse/ActiveRecord
def metadata(required_fields = [:issue_count, :total_issue_weight])
fields = metadata_fields(required_fields)
keys = fields.keys
# TODO: eliminate need for SQL literal fragment
columns = Arel.sql(fields.values_at(*keys).join(', '))
results = item_model.where(id: collection_ids)
results = results.select(columns)
# Failing tests in spec/requests/api/graphql/boards/board_lists_query_spec.rb
::Gitlab::Database.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/417465") do
fields = metadata_fields(required_fields)
keys = fields.keys
# TODO: eliminate need for SQL literal fragment
columns = Arel.sql(fields.values_at(*keys).join(', '))
results = item_model.where(id: collection_ids)
results = results.select(columns)
Hash[keys.zip(results.pluck(columns).flatten)]
Hash[keys.zip(results.pluck(columns).flatten)]
end
end
# rubocop: enable CodeReuse/ActiveRecord

View File

@ -83,18 +83,17 @@ module Issues
params.delete(:work_item_type)
end
base_type = work_item_type&.base_type
# We need to support the legacy input params[:issue_type] even if we don't have the issue_type column anymore.
# In the future only params[:work_item_type] should be provided
base_type = work_item_type&.base_type || params[:issue_type]
if create_issue_type_allowed?(container, base_type)
issue.work_item_type = work_item_type
# Up to this point issue_type might be set to the default, so we need to sync if a work item type is provided
issue.issue_type = base_type
else
# If no work item type was provided or not allowed, we need to set it to issue_type,
# and that includes the column default
issue_type = issue_params[:issue_type] || ::Issue::DEFAULT_ISSUE_TYPE
issue.work_item_type = WorkItems::Type.default_by_type(issue_type)
end
issue.work_item_type = if create_issue_type_allowed?(container, base_type)
work_item_type || WorkItems::Type.default_by_type(base_type)
else
# If no work item type was provided or not allowed, we need to set it to
# the default issue_type
WorkItems::Type.default_by_type(::Issue::DEFAULT_ISSUE_TYPE)
end
end
def model_klass
@ -109,8 +108,6 @@ module Issues
:confidential
]
public_issue_params << :issue_type if create_issue_type_allowed?(container, params[:issue_type])
params.slice(*public_issue_params)
end

View File

@ -32,10 +32,9 @@ module Issues
end
def change_work_item_type(issue)
return unless issue.changed_attributes['issue_type']
return unless params[:issue_type].present?
issue_type = params[:issue_type] || ::Issue::DEFAULT_ISSUE_TYPE
type_id = find_work_item_type_id(issue_type)
type_id = find_work_item_type_id(params[:issue_type])
issue.work_item_type_id = type_id
end
@ -180,16 +179,22 @@ module Issues
end
def handle_issue_type_change(issue)
return unless issue.previous_changes.include?('issue_type')
return unless issue.previous_changes.include?('work_item_type_id')
do_handle_issue_type_change(issue)
end
def do_handle_issue_type_change(issue)
SystemNoteService.change_issue_type(issue, current_user, issue.issue_type_before_last_save)
old_work_item_type = ::WorkItems::Type.find(issue.work_item_type_id_before_last_save).base_type
SystemNoteService.change_issue_type(issue, current_user, old_work_item_type)
::IncidentManagement::IssuableEscalationStatuses::CreateService.new(issue).execute if issue.supports_escalation?
end
override :allowed_update_params
def allowed_update_params(params)
super.except(:issue_type)
end
end
end

View File

@ -2,7 +2,7 @@
.bs-callout.clearfix
%p
= s_("Cohorts|User cohorts are shown for the last %{months_included} months. Only users with activity are counted in the 'New users' column; inactive users are counted separately.") % { months_included: @cohorts[:months_included] }
= link_to sprite_icon('question-o'), help_page_path('user/admin_area/user_cohorts', anchor: 'cohorts'), title: 'About this feature', target: '_blank', rel: 'noopener noreferrer'
= link_to sprite_icon('question-o'), help_page_path('administration/user_cohorts', anchor: 'cohorts'), title: 'About this feature', target: '_blank', rel: 'noopener noreferrer'
.table-holder.d-xl-table
%table.table

View File

@ -3,9 +3,6 @@ description: Schema for all Cell-local tables, ex. namespaces, projects, etc.
allow_cross_joins:
- gitlab_shared
- gitlab_main
# Temporarily allow cross-joins between clusterwide and cell schemas
# This is to be removed once we annotate all cross-joins between those
- gitlab_main_clusterwide
allow_cross_transactions:
- gitlab_internal
- gitlab_shared

View File

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

View File

@ -0,0 +1,96 @@
---
stage: Anti-Abuse
group: Anti-Abuse
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, howto
---
# Review abuse reports **(FREE SELF)**
View and resolve abuse reports from GitLab users.
GitLab administrators can view and [resolve](#resolving-abuse-reports) abuse
reports in the Admin Area.
## Receive notification of abuse reports by email
To receive notifications of new abuse reports by email:
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
1. Select **Admin Area**.
1. Select **Settings > Reporting**.
1. Expand the **Abuse reports** section.
1. Provide an email address and select **Save changes**.
The notification email address can also be set and retrieved
[using the API](../api/settings.md#list-of-settings-that-can-be-accessed-via-api-calls).
## Reporting abuse
To find out more about reporting abuse, see
[abuse reports user documentation](../user/report_abuse.md).
## Resolving abuse reports
To access abuse reports:
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
1. Select **Admin Area**.
1. Select **Abuse Reports**.
There are 3 ways to resolve an abuse report, with a button for each method:
- Remove user & report. This:
- [Deletes the reported user](../user/profile/account/delete_account.md) from the
instance.
- Removes the abuse report from the list.
- [Block user](#blocking-users).
- Remove report. This:
- Removes the abuse report from the list.
- Removes access restrictions for the reported user.
The following is an example of the **Abuse Reports** page:
![abuse-reports-page-image](img/abuse_reports_page_v13_11.png)
### Blocking users
A blocked user cannot sign in or access any repositories, but all of their data
remains.
Blocking a user:
- Leaves them in the abuse report list.
- Changes the **Block user** button to a disabled **Already blocked** button.
The user is notified with the following message:
```plaintext
Your account has been blocked. If you believe this is in error, contact a staff member.
```
After blocking, you can still either:
- Remove the user and report if necessary.
- Remove the report.
The following is an example of a blocked user listed on the **Abuse Reports**
page:
![abuse-report-blocked-user-image](img/abuse_report_blocked_user.png)
NOTE:
Users can be [blocked](../api/users.md#block-user) and
[unblocked](../api/users.md#unblock-user) using the GitLab API.
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
one might have when setting this up, or when something is changed, or on upgrading, it's
important to describe those, too. Think of things that may go wrong and include them here.
This is important to minimize requests for support, and to avoid doc comments with
questions that you know someone might ask.
Each scenario can be a third-level heading, for example `### Getting error message X`.
If you have none to add when creating a doc, leave this section in place
but commented out to help encourage others to add to it in the future. -->

View File

@ -0,0 +1,40 @@
---
stage: none
group: unassigned
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Cohorts **(FREE SELF)**
You can analyze your users' GitLab activities over time.
How do you interpret the user cohorts table? Let's review an example with the
following user cohorts:
![User cohort example](img/cohorts_v13_9_a.png)
For the cohort of March 2020, three users were added to this server and have
been active since this month. One month later (April 2020), two users are still
active. Five months later (August 2020), one user from this cohort is still
active, or 33% of the original cohort of three that joined in March.
The **Inactive users** column shows the number of users who were added during
the month, but who never had any activity in the instance.
How do we measure the activity of users? GitLab considers a user active if:
- The user signs in.
- The user has Git activity (whether push or pull).
- The user visits pages related to dashboards, projects, issues, or merge
requests ([introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/54947) in GitLab 11.8).
- The user uses the API.
- The user uses the GraphQL API.
## View user cohorts
To view user cohorts:
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
1. Select **Admin Area**.
1. Select **Overview > Users**.
1. Select the **Cohorts** tab.

View File

@ -291,8 +291,8 @@ listed in the descriptions of the relevant settings.
| Attribute | Type | Required | Description |
|------------------------------------------|------------------|:------------------------------------:|-------------|
| `admin_mode` | boolean | no | Require administrators to enable Admin Mode by re-authenticating for administrative tasks. |
| `admin_notification_email` | string | no | Deprecated: Use `abuse_notification_email` instead. If set, [abuse reports](../user/admin_area/review_abuse_reports.md) are sent to this address. Abuse reports are always available in the Admin Area. |
| `abuse_notification_email` | string | no | If set, [abuse reports](../user/admin_area/review_abuse_reports.md) are sent to this address. Abuse reports are always available in the Admin Area. |
| `admin_notification_email` | string | no | Deprecated: Use `abuse_notification_email` instead. If set, [abuse reports](../administration/review_abuse_reports.md) are sent to this address. Abuse reports are always available in the Admin Area. |
| `abuse_notification_email` | string | no | If set, [abuse reports](../administration/review_abuse_reports.md) are sent to this address. Abuse reports are always available in the Admin Area. |
| `after_sign_out_path` | string | no | Where to redirect users after logout. |
| `after_sign_up_text` | string | no | Text shown to the user after signing up. |
| `akismet_api_key` | string | required by: `akismet_enabled` | API key for Akismet spam protection. |

View File

@ -281,24 +281,24 @@ changes to prepare the codebase for data split.
One iteration describes one quarter's worth of work.
1. Iteration 1 - FY24Q1
1. [Iteration 1](https://gitlab.com/groups/gitlab-org/-/epics/9667) - FY24Q1
- Data access layer: Initial Admin Area settings are shared across cluster.
- Essential workflows: Allow to share cluster-wide data with database-level data access layer
1. Iteration 2 - FY24Q2
1. [Iteration 2](https://gitlab.com/groups/gitlab-org/-/epics/9813) - FY24Q2
- Essential workflows: User accounts are shared across cluster.
- Essential workflows: User can create group.
1. Iteration 3 - FY24Q3
1. [Iteration 3](https://gitlab.com/groups/gitlab-org/-/epics/10997) - FY24Q3
- Essential workflows: User can create project.
- Essential workflows: User can push to Git repository.
- Cell deployment: Extend GitLab Dedicated to support GCP
- Routing: Technology.
1. Iteration 4 - FY24Q4
1. [Iteration 4](https://gitlab.com/groups/gitlab-org/-/epics/10998) - FY24Q4
- Essential workflows: User can run CI pipeline.
- Essential workflows: User can create issue, merge request, and merge it after it is green.

View File

@ -76,7 +76,7 @@ GitLab administrators can block and unblock users.
To completely prevent access of a user to the GitLab instance,
administrators can choose to block the user.
Users can be blocked [via an abuse report](review_abuse_reports.md#blocking-users),
Users can be blocked [via an abuse report](../../administration/review_abuse_reports.md#blocking-users),
by removing them in LDAP, or directly from the Admin Area. To do this:
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).

View File

@ -1,96 +1,11 @@
---
stage: Anti-Abuse
group: Anti-Abuse
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, howto
redirect_to: '../../administration/review_abuse_reports.md'
remove_date: '2023-10-11'
---
# Review abuse reports **(FREE SELF)**
This document was moved to [another location](../../administration/review_abuse_reports.md).
View and resolve abuse reports from GitLab users.
GitLab administrators can view and [resolve](#resolving-abuse-reports) abuse
reports in the Admin Area.
## Receive notification of abuse reports by email
To receive notifications of new abuse reports by email:
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
1. Select **Admin Area**.
1. Select **Settings > Reporting**.
1. Expand the **Abuse reports** section.
1. Provide an email address and select **Save changes**.
The notification email address can also be set and retrieved
[using the API](../../api/settings.md#list-of-settings-that-can-be-accessed-via-api-calls).
## Reporting abuse
To find out more about reporting abuse, see
[abuse reports user documentation](../report_abuse.md).
## Resolving abuse reports
To access abuse reports:
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
1. Select **Admin Area**.
1. Select **Abuse Reports**.
There are 3 ways to resolve an abuse report, with a button for each method:
- Remove user & report. This:
- [Deletes the reported user](../profile/account/delete_account.md) from the
instance.
- Removes the abuse report from the list.
- [Block user](#blocking-users).
- Remove report. This:
- Removes the abuse report from the list.
- Removes access restrictions for the reported user.
The following is an example of the **Abuse Reports** page:
![abuse-reports-page-image](img/abuse_reports_page_v13_11.png)
### Blocking users
A blocked user cannot sign in or access any repositories, but all of their data
remains.
Blocking a user:
- Leaves them in the abuse report list.
- Changes the **Block user** button to a disabled **Already blocked** button.
The user is notified with the following message:
```plaintext
Your account has been blocked. If you believe this is in error, contact a staff member.
```
After blocking, you can still either:
- Remove the user and report if necessary.
- Remove the report.
The following is an example of a blocked user listed on the **Abuse Reports**
page:
![abuse-report-blocked-user-image](img/abuse_report_blocked_user.png)
NOTE:
Users can be [blocked](../../api/users.md#block-user) and
[unblocked](../../api/users.md#unblock-user) using the GitLab API.
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
one might have when setting this up, or when something is changed, or on upgrading, it's
important to describe those, too. Think of things that may go wrong and include them here.
This is important to minimize requests for support, and to avoid doc comments with
questions that you know someone might ask.
Each scenario can be a third-level heading, for example `### Getting error message X`.
If you have none to add when creating a doc, leave this section in place
but commented out to help encourage others to add to it in the future. -->
<!-- This redirect file can be deleted after <2023-10-11>. -->
<!-- Redirects that point to other docs in the same project expire in three months. -->
<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->

View File

@ -1,40 +1,11 @@
---
stage: none
group: unassigned
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
redirect_to: '../../administration/user_cohorts.md'
remove_date: '2023-10-11'
---
# Cohorts **(FREE SELF)**
This document was moved to [another location](../../administration/user_cohorts.md).
You can analyze your users' GitLab activities over time.
How do you interpret the user cohorts table? Let's review an example with the
following user cohorts:
![User cohort example](img/cohorts_v13_9_a.png)
For the cohort of March 2020, three users were added to this server and have
been active since this month. One month later (April 2020), two users are still
active. Five months later (August 2020), one user from this cohort is still
active, or 33% of the original cohort of three that joined in March.
The **Inactive users** column shows the number of users who were added during
the month, but who never had any activity in the instance.
How do we measure the activity of users? GitLab considers a user active if:
- The user signs in.
- The user has Git activity (whether push or pull).
- The user visits pages related to dashboards, projects, issues, or merge
requests ([introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/54947) in GitLab 11.8).
- The user uses the API.
- The user uses the GraphQL API.
## View user cohorts
To view user cohorts:
1. On the left sidebar, expand the top-most chevron (**{chevron-down}**).
1. Select **Admin Area**.
1. Select **Overview > Users**.
1. Select the **Cohorts** tab.
<!-- This redirect file can be deleted after <2023-10-11>. -->
<!-- Redirects that point to other docs in the same project expire in three months. -->
<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->

View File

@ -76,7 +76,8 @@ For example, the parameter `query=gitlab-org/gitlab-ui,gitlab-org/plan-stage` di
### Using YAML configuration
To change the default content of the page, you need to create a YAML configuration file in a project of your choice. Query parameters can still be used to override the YAML configuration.
To customize the default content of the page, you need to create a YAML configuration file in a project of your choice. In this file you can define various settings and parameters, such as title, description, and number of panels and labels filters. The file is schema-driven and managed with version control systems like Git. This enables tracking and maintaining a history of configuration changes, reverting to previous versions if necessary, and collaborating effectively with team members.
Query parameters can still be used to override the YAML configuration.
First, you need to set up the project.
@ -107,12 +108,25 @@ description: 'Custom description'
# title - Change the title of the panel. [optional]
# data.namespace - The Group or Project path to use for the chart panel.
# data.exclude_metrics - Hide rows by metric ID from the chart panel.
# data.filter_labels -
# Only show results for data that matches the queried label(s). If multiple labels are provided,
# only a single label needs to match for the data to be included in the results.
# Compatible metrics (other metrics will be automatically excluded):
# * lead_time
# * cycle_time
# * issues
# * issues_completed
# * merge_request_throughput
# (This option is dependant on the `vsd_graphql_dora_and_flow_metrics` feature.)
panels:
- title: 'My Custom Project'
data:
namespace: group/my-custom-project
- data:
namespace: group/another-project
filter_labels:
- in_development
- in_review
- title: 'My Custom Group'
data:
namespace: group/my-custom-group
@ -131,6 +145,9 @@ panels:
namespace: my-group
```
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For an overview of editing label filters in the configuration file, see [GitLab Value Streams Dashboard - Label filters demo](https://www.youtube.com/watch?v=4qDAHCxCfik).
## Dashboard metrics and drill-down reports
| Metric | Description | Drill-down report | Documentation page | ID |

View File

@ -71,7 +71,7 @@ When deleting users, you can either:
An alternative to deleting is [blocking a user](../../admin_area/moderate_users.md#block-a-user).
When a user is deleted from an [abuse report](../../admin_area/review_abuse_reports.md) or spam log, these associated
When a user is deleted from an [abuse report](../../../administration/review_abuse_reports.md) or spam log, these associated
records are always removed.
The deleting associated records option can be requested in the [API](../../../api/users.md#user-deletion) as well as

View File

@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
You can report abuse from other GitLab users to GitLab administrators.
A GitLab administrator [can then choose](admin_area/review_abuse_reports.md) to:
A GitLab administrator [can then choose](../administration/review_abuse_reports.md) to:
- Remove the user, which deletes them from the instance.
- Block the user, which denies them access to the instance.
@ -66,4 +66,4 @@ A URL to the reported user's comment is pre-filled in the abuse report's
## Related topics
- [Abuse reports administration documentation](admin_area/review_abuse_reports.md)
- [Abuse reports administration documentation](../administration/review_abuse_reports.md)

View File

@ -29,6 +29,7 @@ module API
# rubocop: disable CodeReuse/ActiveRecord
def retrieve_members(source, params:, deep: false)
members = deep ? find_all_members(source) : source_members(source).connected_to_user
members = members.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/417456")
members = members.includes(:user)
members = members.references(:user).merge(User.search(params[:query], use_minimum_char_limit: false)) if params[:query].present?
members = members.where(user_id: params[:user_ids]) if params[:user_ids].present?

View File

@ -58,8 +58,11 @@ module Backup
end
def enqueue_consecutive_projects
project_relation.find_each(batch_size: 1000) do |project|
enqueue_project(project)
cross_join_issue = "https://gitlab.com/gitlab-org/gitlab/-/issues/417467"
::Gitlab::Database.allow_cross_joins_across_databases(url: cross_join_issue) do
project_relation.find_each(batch_size: 1000) do |project|
enqueue_project(project)
end
end
end

View File

@ -65,10 +65,13 @@ module Banzai
# The keys of this Hash are the namespace paths, the values the
# corresponding Namespace objects.
def namespaces
@namespaces ||= Namespace.eager_load(:owner, :route)
.where_full_path_in(usernames)
.index_by(&:full_path)
.transform_keys(&:downcase)
cross_join_issue = "https://gitlab.com/gitlab-org/gitlab/-/issues/417466"
Gitlab::Database.allow_cross_joins_across_databases(url: cross_join_issue) do
@namespaces ||= Namespace.eager_load(:owner, :route)
.where_full_path_in(usernames)
.index_by(&:full_path)
.transform_keys(&:downcase)
end
end
# Returns all usernames referenced in the current document.

View File

@ -97,9 +97,12 @@ module Banzai
def find_users_for_groups(ids)
return [] if ids.empty?
User.joins(:group_members).where(members: {
source_id: Namespace.where(id: ids).where('mentions_disabled IS NOT TRUE').select(:id)
}).to_a
cross_join_issue = "https://gitlab.com/gitlab-org/gitlab/-/issues/417466"
::Gitlab::Database.allow_cross_joins_across_databases(url: cross_join_issue) do
User.joins(:group_members).where(members: {
source_id: Namespace.where(id: ids).where('mentions_disabled IS NOT TRUE').select(:id)
}).to_a
end
end
def find_users_for_projects(ids)

View File

@ -13,6 +13,7 @@ module Gitlab
# rubocop:disable CodeReuse/ActiveRecord
def users
groups = group.self_and_hierarchy_intersecting_with_user_groups(current_user)
groups = groups.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/417455")
members = GroupMember.where(group: groups).non_invite
users = super

View File

@ -93,7 +93,7 @@ module Gitlab
when :notes, :Note then setup_note
when :'Ci::Pipeline' then setup_pipeline
when *BUILD_MODELS then setup_build
when :issues then setup_issue
when :issues then setup_work_item
when :'Ci::PipelineSchedule' then setup_pipeline_schedule
when :'ProtectedBranch::MergeAccessLevel' then setup_protected_branch_access_level
when :'ProtectedBranch::PushAccessLevel' then setup_protected_branch_access_level
@ -169,13 +169,11 @@ module Gitlab
end
end
def setup_issue
def setup_work_item
@relation_hash['relative_position'] = compute_relative_position
issue_type = @relation_hash['issue_type']
issue_type = @relation_hash.delete('issue_type')
@relation_hash['work_item_type'] ||= ::WorkItems::Type.default_by_type(issue_type) if issue_type
# Make sure issue_type is in sync with work_item_type if either was provided in the export file
@relation_hash['issue_type'] = @relation_hash['work_item_type'].base_type if @relation_hash['work_item_type']
end
def setup_release

View File

@ -259,7 +259,6 @@ module Gitlab
current_user.can?(:"set_#{quick_action_target.issue_type}_metadata", quick_action_target)
end
command :promote_to_incident do
@updates[:issue_type] = :incident
@updates[:work_item_type] = ::WorkItems::Type.default_by_type(:incident)
end

View File

@ -1204,6 +1204,11 @@ msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
msgstr[0] ""
msgstr[1] ""
msgid "%{strong_start}%{terraform_states_count}%{strong_end} Terraform State"
msgid_plural "%{strong_start}%{terraform_states_count}%{strong_end} Terraform States"
msgstr[0] ""
msgstr[1] ""
msgid "%{tabname} changed"
msgstr ""
@ -14023,6 +14028,9 @@ msgstr ""
msgid "DORA4Metrics|Failed to load comparison chart for Namespace: %{fullPath}"
msgstr ""
msgid "DORA4Metrics|Failed to load labels matching the filter: %{labels}"
msgstr ""
msgid "DORA4Metrics|Filtered by"
msgstr ""
@ -14684,6 +14692,9 @@ msgstr ""
msgid "Date range must be shorter than %{max_range} days."
msgstr ""
msgid "Date range too large"
msgstr ""
msgid "Date to enact enforcement on newly created namespaces"
msgstr ""
@ -24816,6 +24827,9 @@ msgstr ""
msgid "Invalid date range"
msgstr ""
msgid "Invalid dates set"
msgstr ""
msgid "Invalid feature"
msgstr ""

View File

@ -57,7 +57,7 @@
"@gitlab/favicon-overlay": "2.0.0",
"@gitlab/fonts": "^1.3.0",
"@gitlab/svgs": "3.55.0",
"@gitlab/ui": "64.20.0",
"@gitlab/ui": "64.20.1",
"@gitlab/visual-review-tools": "1.7.3",
"@gitlab/web-ide": "0.0.1-dev-20230713160749",
"@mattiasbuelens/web-streams-adapter": "^0.1.0",

View File

@ -55,7 +55,7 @@ FactoryBot.define do
end
trait :for_issue do
target { association(:issue, issue_type: :issue) }
target { association(:issue) }
target_type { 'Issue' }
end

View File

@ -8,7 +8,6 @@ FactoryBot.define do
author { project.creator }
updated_by { author }
relative_position { RelativePositioning::START_POSITION }
issue_type { :issue }
association :work_item_type, :default
trait :confidential do
@ -66,38 +65,35 @@ FactoryBot.define do
end
end
trait :issue do
association :work_item_type, :default, :issue
end
trait :requirement do
issue_type { :requirement }
association :work_item_type, :default, :requirement
end
trait :task do
issue_type { :task }
association :work_item_type, :default, :task
end
trait :objective do
issue_type { :objective }
association :work_item_type, :default, :objective
end
trait :key_result do
issue_type { :key_result }
association :work_item_type, :default, :key_result
end
trait :incident do
issue_type { :incident }
association :work_item_type, :default, :incident
end
trait :test_case do
issue_type { :test_case }
association :work_item_type, :default, :test_case
end
factory :incident do
issue_type { :incident }
association :work_item_type, :default, :incident
# An escalation status record is created for all incidents

View File

@ -7,7 +7,6 @@ FactoryBot.define do
author { project.creator }
updated_by { author }
relative_position { RelativePositioning::START_POSITION }
issue_type { :issue }
association :work_item_type, :default
trait :confidential do
@ -27,23 +26,23 @@ FactoryBot.define do
closed_at { Time.now }
end
trait :issue do
association :work_item_type, :default, :issue
end
trait :task do
issue_type { :task }
association :work_item_type, :default, :task
end
trait :incident do
issue_type { :incident }
association :work_item_type, :default, :incident
end
trait :requirement do
issue_type { :requirement }
association :work_item_type, :default, :requirement
end
trait :test_case do
issue_type { :test_case }
association :work_item_type, :default, :test_case
end
@ -52,12 +51,10 @@ FactoryBot.define do
end
trait :objective do
issue_type { :objective }
association :work_item_type, :default, :objective
end
trait :key_result do
issue_type { :key_result }
association :work_item_type, :default, :key_result
end

View File

@ -23,6 +23,11 @@ FactoryBot.define do
namespace { nil }
end
trait :issue do
base_type { WorkItems::Type.base_types[:issue] }
icon_name { 'issue-type-issue' }
end
trait :incident do
base_type { WorkItems::Type.base_types[:incident] }
icon_name { 'issue-type-incident' }

View File

@ -105,7 +105,6 @@ RSpec.describe GraphQL::Query, type: :request do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project) }
let_it_be(:issue_type) { 'issue' }
before_all do
project.add_reporter(user)
@ -128,8 +127,7 @@ RSpec.describe GraphQL::Query, type: :request do
title: '15.2',
start_date: Date.new(2020, 7, 1),
due_date: Date.new(2020, 7, 30)
),
issue_type: issue_type
)
)
post_graphql(query, current_user: user, variables: { projectPath: project.full_path, iid: issue.iid.to_s })

View File

@ -19,8 +19,7 @@ RSpec.describe Mutations::Issues::Create do
description: 'new description',
confidential: true,
due_date: Date.tomorrow,
discussion_locked: true,
issue_type: 'issue'
discussion_locked: true
}
end
@ -29,7 +28,8 @@ RSpec.describe Mutations::Issues::Create do
project_path: project.full_path,
milestone_id: milestone.to_global_id,
labels: [project_label1.title, project_label2.title, new_label1, new_label2],
assignee_ids: [assignee1.to_global_id, assignee2.to_global_id]
assignee_ids: [assignee1.to_global_id, assignee2.to_global_id],
issue_type: 'issue'
}.merge(expected_attributes)
end

View File

@ -266,7 +266,6 @@ RSpec.describe GitlabSchema.types['Issue'] do
context 'for an incident' do
before do
issue.update!(
issue_type: WorkItems::Type.base_types[:incident],
work_item_type: WorkItems::Type.default_by_type(:incident)
)
end

View File

@ -275,7 +275,7 @@ RSpec.describe IntegrationsHelper, feature_category: :integrations do
with_them do
before do
issue.assign_attributes(issue_type: issue_type, work_item_type: WorkItems::Type.default_by_type(issue_type))
issue.assign_attributes(work_item_type: WorkItems::Type.default_by_type(issue_type))
issue.save!(validate: false)
end

View File

@ -2,7 +2,8 @@
require 'spec_helper'
RSpec.describe Gitlab::BackgroundMigration::BatchingStrategies::PrimaryKeyBatchingStrategy, '#next_batch' do
RSpec.describe Gitlab::BackgroundMigration::BatchingStrategies::PrimaryKeyBatchingStrategy,
'#next_batch', feature_category: :database do
let(:batching_strategy) { described_class.new(connection: ActiveRecord::Base.connection) }
let(:namespaces) { table(:namespaces) }
@ -64,7 +65,7 @@ RSpec.describe Gitlab::BackgroundMigration::BatchingStrategies::PrimaryKeyBatchi
context 'when scope has a join which makes the column name ambiguous' do
let(:job_class) do
Class.new(Gitlab::BackgroundMigration::BatchedMigrationJob) do
scope_to ->(r) { r.joins('LEFT JOIN users ON users.id = namespaces.owner_id') }
scope_to ->(r) { r.joins('LEFT JOIN namespaces as parents ON parents.id = namespaces.parent_id') }
end
end

View File

@ -127,22 +127,6 @@ RSpec.describe Issue, feature_category: :team_planning do
end
end
describe 'issue_type' do
let(:issue) { build(:issue, issue_type: issue_type) }
context 'when a valid type' do
let(:issue_type) { :issue }
it { is_expected.to eq(true) }
end
context 'empty type' do
let(:issue_type) { nil }
it { is_expected.to eq(false) }
end
end
describe '#allowed_work_item_type_change' do
where(:old_type, :new_type, :is_valid) do
:issue | :incident | true
@ -161,7 +145,7 @@ RSpec.describe Issue, feature_category: :team_planning do
it 'is possible to change type only between selected types' do
issue = create(:issue, old_type, project: reusable_project)
issue.assign_attributes(work_item_type: WorkItems::Type.default_by_type(new_type), issue_type: new_type)
issue.assign_attributes(work_item_type: WorkItems::Type.default_by_type(new_type))
expect(issue.valid?).to eq(is_valid)
end
@ -272,7 +256,7 @@ RSpec.describe Issue, feature_category: :team_planning do
expect(issue.work_item_type_id).to eq(issue_type.id)
expect(WorkItems::Type).not_to receive(:default_by_type)
issue.update!(work_item_type: incident_type, issue_type: :incident)
issue.update!(work_item_type: incident_type)
expect(issue.work_item_type_id).to eq(incident_type.id)
end
@ -301,36 +285,13 @@ RSpec.describe Issue, feature_category: :team_planning do
expect(issue.work_item_type_id).to be_nil
expect(WorkItems::Type).not_to receive(:default_by_type)
issue.update!(work_item_type: incident_type, issue_type: :incident)
issue.update!(work_item_type: incident_type)
expect(issue.work_item_type_id).to eq(incident_type.id)
end
end
end
describe '#check_issue_type_in_sync' do
it 'raises an error if issue_type is out of sync' do
issue = build(:issue, issue_type: :issue, work_item_type: WorkItems::Type.default_by_type(:task))
expect do
issue.save!
end.to raise_error(Issue::IssueTypeOutOfSyncError)
end
it 'uses attributes to compare both issue_type values' do
issue_type = WorkItems::Type.default_by_type(:issue)
issue = build(:issue, issue_type: :issue, work_item_type: issue_type)
attributes = double(:attributes)
allow(issue).to receive(:attributes).and_return(attributes)
expect(attributes).to receive(:[]).with('issue_type').twice.and_return('issue')
expect(issue_type).to receive(:base_type).and_call_original
issue.save!
end
end
describe '#record_create_action' do
it 'records the creation action after saving' do
expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).to receive(:track_issue_created_action)
@ -1906,7 +1867,7 @@ RSpec.describe Issue, feature_category: :team_planning do
with_them do
before do
issue.update!(issue_type: issue_type, work_item_type: WorkItems::Type.default_by_type(issue_type))
issue.update!(work_item_type: WorkItems::Type.default_by_type(issue_type))
end
specify do
@ -1926,7 +1887,7 @@ RSpec.describe Issue, feature_category: :team_planning do
with_them do
before do
issue.update!(issue_type: issue_type, work_item_type: WorkItems::Type.default_by_type(issue_type))
issue.update!(work_item_type: WorkItems::Type.default_by_type(issue_type))
end
specify do
@ -2070,51 +2031,4 @@ RSpec.describe Issue, feature_category: :team_planning do
expect { issue1.unsubscribe_email_participant(email) }.not_to change { issue2.issue_email_participants.count }
end
end
describe 'issue_type enum generated methods' do
describe '#<issue_type>?' do
let_it_be(:issue) { create(:issue, project: reusable_project) }
where(issue_type: WorkItems::Type.base_types.keys)
with_them do
it 'raises an error if called' do
expect { issue.public_send("#{issue_type}?".to_sym) }.to raise_error(
Issue::ForbiddenColumnUsed,
a_string_matching(/`issue\.#{issue_type}\?` uses the `issue_type` column underneath/)
)
end
end
end
describe '.<issue_type> scopes' do
where(issue_type: WorkItems::Type.base_types.keys)
with_them do
it 'raises an error if called' do
expect { Issue.public_send(issue_type.to_sym) }.to raise_error(
Issue::ForbiddenColumnUsed,
a_string_matching(/`Issue\.#{issue_type}` uses the `issue_type` column underneath/)
)
end
context 'when called in a production environment' do
before do
stub_rails_env('production')
end
it 'returns issues scoped by type instead of raising an error' do
issue = create(
:issue,
issue_type: issue_type,
work_item_type: WorkItems::Type.default_by_type(issue_type),
project: reusable_project
)
expect(Issue.public_send(issue_type.to_sym)).to contain_exactly(issue)
end
end
end
end
end
end

View File

@ -304,22 +304,6 @@ RSpec.describe WorkItem, feature_category: :portfolio_management do
describe 'validations' do
subject { work_item.valid? }
describe 'issue_type' do
let(:work_item) { build(:work_item, issue_type: issue_type) }
context 'when a valid type' do
let(:issue_type) { :issue }
it { is_expected.to eq(true) }
end
context 'empty type' do
let(:issue_type) { nil }
it { is_expected.to eq(false) }
end
end
describe 'confidentiality' do
let_it_be(:project) { create(:project) }

View File

@ -51,8 +51,8 @@ RSpec.describe WorkItems::ParentLink, feature_category: :portfolio_management do
it 'validates if child can be added to the parent' do
parent_type = WorkItems::Type.default_by_type(parent_type_sym)
child_type = WorkItems::Type.default_by_type(child_type_sym)
parent = build(:work_item, issue_type: parent_type_sym, work_item_type: parent_type, project: project)
child = build(:work_item, issue_type: child_type_sym, work_item_type: child_type, project: project)
parent = build(:work_item, work_item_type: parent_type, project: project)
child = build(:work_item, work_item_type: child_type, project: project)
link = build(:parent_link, work_item: child, work_item_parent: parent)
expect(link.valid?).to eq(is_valid)

View File

@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe WorkItems::Widgets::Milestone do
let_it_be(:project) { create(:project) }
let_it_be(:milestone) { create(:milestone, project: project) }
let_it_be(:work_item) { create(:work_item, :issue, project: project, milestone: milestone) }
let_it_be(:work_item) { create(:work_item, project: project, milestone: milestone) }
describe '.type' do
subject { described_class.type }

View File

@ -271,7 +271,7 @@ RSpec.describe NotePolicy, feature_category: :team_planning do
end
context 'when noteable is issue' do
let(:noteable) { create(:work_item, :issue, project: project) }
let(:noteable) { create(:work_item, project: project) }
let(:note) { create(:note, system: true, noteable: noteable, author: user, project: project) }
it_behaves_like 'user can read the note'

View File

@ -388,6 +388,35 @@ RSpec.describe ProjectPresenter do
end
end
describe '#terraform_states_anchor_data' do
using RSpec::Parameterized::TableSyntax
let(:anchor_goto_terraform) do
have_attributes(
is_link: true,
label: a_string_including(project.terraform_states.size.to_s),
link: presenter.project_terraform_index_path(project)
)
end
where(:terraform_states_exists, :can_read_terraform_state, :expected_result) do
true | true | ref(:anchor_goto_terraform)
true | false | nil
false | true | nil
false | false | nil
end
with_them do
before do
allow(project.terraform_states).to receive(:exists?).and_return(terraform_states_exists)
allow(presenter).to receive(:can?).with(user, :read_terraform_state,
project).and_return(can_read_terraform_state)
end
it { expect(presenter.terraform_states_anchor_data).to match(expected_result) }
end
end
describe '#tags_anchor_data' do
it 'returns tags data' do
expect(presenter.tags_anchor_data).to have_attributes(

View File

@ -30,7 +30,7 @@ RSpec.describe API::Discussions, feature_category: :team_planning do
end
context 'when noteable is a WorkItem' do
let!(:work_item) { create(:work_item, :issue, project: project, author: user) }
let!(:work_item) { create(:work_item, project: project, author: user) }
let!(:work_item_note) { create(:discussion_note_on_issue, noteable: work_item, project: project, author: user) }
let(:parent) { project }

View File

@ -51,9 +51,7 @@ RSpec.describe 'Update of an existing issue', feature_category: :team_planning d
expect do
post_graphql_mutation(mutation, current_user: current_user)
issue.reload
end.to change { issue.work_item_type.base_type }.from('issue').to('incident').and(
change(issue, :issue_type).from('issue').to('incident')
)
end.to change { issue.work_item_type.base_type }.from('issue').to('incident')
end
end

View File

@ -105,7 +105,7 @@ RSpec.describe 'Adding a Note', feature_category: :team_planning do
context 'as work item' do
let_it_be(:project) { create(:project) }
let_it_be(:noteable) { create(:work_item, :issue, project: project) }
let_it_be(:noteable) { create(:work_item, project: project) }
context 'when using internal param' do
let(:variables_extra) { { internal: true } }

View File

@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe 'Destroying a Note', feature_category: :team_planning do
include GraphqlHelpers
let(:noteable) { create(:work_item, :issue) }
let(:noteable) { create(:work_item) }
let!(:note) { create(:note, noteable: noteable, project: noteable.project) }
let(:global_note_id) { GitlabSchema.id_from_object(note).to_s }
let(:variables) { { id: global_note_id } }

View File

@ -41,7 +41,7 @@ RSpec.describe 'Updating a Note', feature_category: :team_planning do
it_behaves_like 'a Note mutation update only with quick actions'
context 'for work item' do
let(:noteable) { create(:work_item, :issue) }
let(:noteable) { create(:work_item) }
let(:note) { create(:note, noteable: noteable, project: noteable.project, note: original_body) }
it_behaves_like 'a Note mutation updates a note successfully'

View File

@ -45,7 +45,6 @@ RSpec.describe IssueSidebarBasicEntity do
context 'for an incident issue' do
before do
issue.update!(
issue_type: WorkItems::Type.base_types[:incident],
work_item_type: WorkItems::Type.default_by_type(:incident)
)
end

View File

@ -20,7 +20,7 @@ RSpec.describe Issuable::DiscussionsListService, feature_category: :team_plannin
it_behaves_like 'listing issuable discussions', :guest, 1, 7
context 'without notes widget' do
let_it_be(:issuable) { create(:work_item, :issue, project: project) }
let_it_be(:issuable) { create(:work_item, project: project) }
before do
WorkItems::Type.default_by_type(:issue).widget_definitions.find_by_widget_type(:notes).update!(disabled: true)

View File

@ -205,7 +205,6 @@ RSpec.describe Issues::BuildService, feature_category: :team_planning do
issue = build_issue(**issue_params)
expect(issue.work_item_type_id).to eq(work_item_type_id)
expect(issue.attributes['issue_type']).to eq(resulting_issue_type)
end
end
end

View File

@ -182,7 +182,7 @@ RSpec.describe Notes::QuickActionsService, feature_category: :team_planning do
context 'on an incident' do
before do
issue.update!(issue_type: :incident, work_item_type: WorkItems::Type.default_by_type(:incident))
issue.update!(work_item_type: WorkItems::Type.default_by_type(:incident))
end
it 'leaves the note empty' do
@ -224,7 +224,7 @@ RSpec.describe Notes::QuickActionsService, feature_category: :team_planning do
context 'on an incident' do
before do
issue.update!(issue_type: :incident, work_item_type: WorkItems::Type.default_by_type(:incident))
issue.update!(work_item_type: WorkItems::Type.default_by_type(:incident))
end
it 'leaves the note empty' do

View File

@ -44,7 +44,7 @@ RSpec.describe WorkItems::UpdateService, feature_category: :team_planning do
context 'when work item type is not the default Issue' do
before do
task_type = WorkItems::Type.default_by_type(:task)
work_item.update_columns(issue_type: task_type.base_type, work_item_type_id: task_type.id)
work_item.update_columns(work_item_type_id: task_type.id)
end
it 'does not apply the quick action' do
@ -55,7 +55,7 @@ RSpec.describe WorkItems::UpdateService, feature_category: :team_planning do
end
context 'when work item type is the default Issue' do
let(:issue) { create(:work_item, :issue, description: '') }
let(:issue) { create(:work_item, description: '') }
it 'applies the quick action' do
expect do

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true
# This module tries to discover and prevent cross-joins across tables
# This will forbid usage of tables between CI and main database
# This will forbid usage of tables of different gitlab_schemas
# on a same query unless explicitly allowed by. This will change execution
# from a given point to allow cross-joins. The state will be cleared
# on a next test run.

View File

@ -160,7 +160,7 @@ RSpec.shared_examples 'work item supports type change via quick actions' do
let(:body) { "Updating type.\n/type Issue" }
before do
noteable.update!(work_item_type: task_type, issue_type: task_type.base_type)
noteable.update!(work_item_type: task_type)
end
it 'updates type' do

View File

@ -532,7 +532,7 @@ RSpec.shared_examples 'graphql issue list request spec' do
end
before do
issue_a.update_columns(issue_type: WorkItems::Type.base_types[:incident], work_item_type_id: incident_type.id)
issue_a.update_columns(work_item_type_id: incident_type.id)
end
it 'returns the escalation status values' do

View File

@ -36,7 +36,7 @@ RSpec.describe IncidentManagement::CloseIncidentWorker, feature_category: :incid
context 'when issue type is not incident' do
before do
issue.update!(issue_type: :issue, work_item_type: WorkItems::Type.default_by_type(:issue))
issue.update!(work_item_type: WorkItems::Type.default_by_type(:issue))
end
it_behaves_like 'does not call the close issue service'

View File

@ -84,6 +84,12 @@ func TestSetProperContentTypeAndDisposition(t *testing.T) {
contentDisposition: "attachment",
body: "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 330 82\"><title>SVG logo combined with the W3C logo, set horizontally</title><desc>The logo combines three entities displayed horizontall</desc><metadata>",
},
{
desc: "Incomplete SVG start tag",
contentType: "image/svg+xml",
contentDisposition: "attachment",
body: "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"",
},
{
desc: "Application type",
contentType: "application/octet-stream",

View File

@ -13,7 +13,7 @@ import (
var (
htmlCommentRegex = regexp.MustCompile(`(?i)<!--([\s\S]*?)-->`)
svgRegex = regexp.MustCompile(`(?i)^\s*(?:<\?xml[^>]*>\s*)?(?:<!doctype svg[^>]*>\s*)?<svg[^>]*>`)
svgRegex = regexp.MustCompile(`(?i)^\s*(?:<\?xml[^>]*>\s*)?(?:<!doctype svg[^>]*>\s*)?<svg[^>]*`)
)
// isBinary checks if the given buffer is a binary file.

View File

@ -1132,10 +1132,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.55.0.tgz#c67c5dddf54c400485762aff6a693e1f5a643739"
integrity sha512-1wuXRGhrWKfWXSM9ZI1aRHlZ0wv4X7tJjDil+AQVjPBANB6oBXAPAiga+qkzkBHss7TzyOjY7OytG/9L5weDLg==
"@gitlab/ui@64.20.0":
version "64.20.0"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-64.20.0.tgz#ee7e0bdee185cfb18c6b540d79d2a88839a76f61"
integrity sha512-lQJP6twO6BhAsLj5FO6vCrGCjgSoNCvrZGxJCAx0FZrI8Dn/+DGiML2mqmmI7WG53+s5rV/xgMniUwBN2TQa0Q==
"@gitlab/ui@64.20.1":
version "64.20.1"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-64.20.1.tgz#4ca5ca7a854be5c15afcc464d16498b9b833ad6e"
integrity sha512-yB4gRRzQCIQxxHnD50j3uOAcg5mhSBw9+tRi9kDqn+CxozDUNC/SNfTy+v7cTLJBn2mdxHfw++cuJcH3gRajxQ==
dependencies:
"@floating-ui/dom" "1.2.9"
bootstrap-vue "2.23.1"