- {{
- s__(
- 'GrafanaIntegration|Set up Grafana authentication to embed Grafana panels in GitLab Flavored Markdown.',
- )
- }}
-
- {{ s__('MetricsSettings|Manage metrics dashboard settings.') }}
-
diff --git a/app/assets/javascripts/work_items/components/work_item_award_emoji.vue b/app/assets/javascripts/work_items/components/work_item_award_emoji.vue
index 91f87be1233..948258fbee6 100644
--- a/app/assets/javascripts/work_items/components/work_item_award_emoji.vue
+++ b/app/assets/javascripts/work_items/components/work_item_award_emoji.vue
@@ -33,6 +33,9 @@ export default {
currentUserId() {
return window.gon.current_user_id;
},
+ currentUserFullName() {
+ return window.gon.current_user_fullname;
+ },
/**
* Parse and convert award emoji list to a format that AwardsList can understand
*/
@@ -42,15 +45,18 @@ export default {
name: emoji.name,
user: {
id: getIdFromGraphQLId(emoji.user.id),
+ name: emoji.user.name,
},
}));
},
},
methods: {
handleAward(name) {
- // Decide action based on emoji is already present
+ // Decide action based on emoji given by current user.
const action =
- this.awards.findIndex((emoji) => emoji.name === name) > -1
+ this.awards.findIndex(
+ (emoji) => emoji.name === name && emoji.user.id === this.currentUserId,
+ ) > -1
? EMOJI_ACTION_REMOVE
: EMOJI_ACTION_ADD;
const inputVariables = {
@@ -96,13 +102,19 @@ export default {
__typename: 'AwardEmoji',
user: {
id: convertToGraphQLId(TYPENAME_USER, this.currentUserId),
+ name: this.currentUserFullName,
__typename: 'UserCore',
},
},
];
// Exclude the award emoji node in case of remove action
if (action === EMOJI_ACTION_REMOVE) {
- awardEmojiNodes = [...this.awardEmoji.nodes.filter((emoji) => emoji.name !== name)];
+ awardEmojiNodes = [
+ ...this.awardEmoji.nodes.filter(
+ (emoji) =>
+ !(emoji.name === name && getIdFromGraphQLId(emoji.user.id) === this.currentUserId),
+ ),
+ ];
}
return {
workItemUpdate: {
diff --git a/app/assets/javascripts/work_items/graphql/award_emoji.fragment.graphql b/app/assets/javascripts/work_items/graphql/award_emoji.fragment.graphql
index 85b88990cd6..bed09974ef5 100644
--- a/app/assets/javascripts/work_items/graphql/award_emoji.fragment.graphql
+++ b/app/assets/javascripts/work_items/graphql/award_emoji.fragment.graphql
@@ -2,5 +2,6 @@ fragment AwardEmojiFragment on AwardEmoji {
name
user {
id
+ name
}
}
diff --git a/app/assets/stylesheets/framework/diffs.scss b/app/assets/stylesheets/framework/diffs.scss
index 6c40781670a..192cb82aaab 100644
--- a/app/assets/stylesheets/framework/diffs.scss
+++ b/app/assets/stylesheets/framework/diffs.scss
@@ -1,6 +1,6 @@
// Common
.diff-file {
- margin-bottom: $gl-padding;
+ padding-bottom: $gl-padding;
&.has-body {
.file-title {
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index 45a7901b2c4..8d2146cddc5 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -56,7 +56,7 @@ class Admin::UsersController < Admin::ApplicationController
log_impersonation_event
- flash[:alert] = format(_("You are now impersonating %{username}"), username: user.username)
+ flash[:notice] = format(_("You are now impersonating %{username}"), username: user.username)
redirect_to root_path
else
diff --git a/app/controllers/concerns/web_ide_csp.rb b/app/controllers/concerns/web_ide_csp.rb
index c2d66abb538..0327020a0c2 100644
--- a/app/controllers/concerns/web_ide_csp.rb
+++ b/app/controllers/concerns/web_ide_csp.rb
@@ -5,25 +5,27 @@ module WebIdeCSP
included do
before_action :include_web_ide_csp
+ end
- # We want to include frames from `/assets/webpack` of the request's host to
- # support URL flexibility with the Web IDE.
- # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/118875
- def include_web_ide_csp
- return if request.content_security_policy.directives.blank?
+ # We want to include frames from `/assets/webpack` of the request's host to
+ # support URL flexibility with the Web IDE.
+ # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/118875
+ def include_web_ide_csp
+ return if request.content_security_policy.directives.blank?
- base_uri = URI(request.url)
- base_uri.path = ::Gitlab.config.gitlab.relative_url_root || '/'
- # `.path +=` handles combining `x/` and `/foo`
- base_uri.path += '/assets/webpack/'
- webpack_url = base_uri.to_s
+ base_uri = URI(request.url)
+ base_uri.path = ::Gitlab.config.gitlab.relative_url_root || '/'
+ # `.path +=` handles combining `x/` and `/foo`
+ base_uri.path += '/assets/webpack/'
+ webpack_url = base_uri.to_s
- default_src = Array(request.content_security_policy.directives['default-src'] || [])
- request.content_security_policy.directives['frame-src'] ||= default_src
- request.content_security_policy.directives['frame-src'].concat([webpack_url, 'https://*.vscode-cdn.net/'])
+ default_src = Array(request.content_security_policy.directives['default-src'] || [])
+ request.content_security_policy.directives['frame-src'] ||= default_src
+ request.content_security_policy.directives['frame-src'].concat([webpack_url, 'https://*.vscode-cdn.net/'])
- request.content_security_policy.directives['worker-src'] ||= default_src
- request.content_security_policy.directives['worker-src'].concat([webpack_url])
- end
+ request.content_security_policy.directives['worker-src'] ||= default_src
+ request.content_security_policy.directives['worker-src'].concat([webpack_url])
end
end
+
+WebIdeCSP.prepend_mod_with('WebIdeCSP')
diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb
index f91ec55573d..0db26c544fa 100644
--- a/app/controllers/projects/environments_controller.rb
+++ b/app/controllers/projects/environments_controller.rb
@@ -25,6 +25,10 @@ class Projects::EnvironmentsController < Projects::ApplicationController
push_frontend_feature_flag(:kas_user_access_project, @project)
end
+ before_action only: [:edit, :new] do
+ push_frontend_feature_flag(:environment_settings_to_graphql, @project)
+ end
+
before_action :authorize_read_environment!, except: [:metrics, :additional_metrics, :metrics_dashboard, :metrics_redirect]
before_action :authorize_create_environment!, only: [:new, :create]
before_action :authorize_stop_environment!, only: [:stop]
diff --git a/app/models/abuse_report.rb b/app/models/abuse_report.rb
index 55b1aff51da..236eaf92546 100644
--- a/app/models/abuse_report.rb
+++ b/app/models/abuse_report.rb
@@ -12,13 +12,15 @@ class AbuseReport < ApplicationRecord
cache_markdown_field :message, pipeline: :single_line
- belongs_to :reporter, class_name: 'User'
- belongs_to :user
+ belongs_to :reporter, class_name: 'User', inverse_of: :reported_abuse_reports
+ belongs_to :user, inverse_of: :abuse_reports
+ belongs_to :resolved_by, class_name: 'User', inverse_of: :resolved_abuse_reports
+ belongs_to :assignee, class_name: 'User', inverse_of: :assigned_abuse_reports
has_many :events, class_name: 'ResourceEvents::AbuseReportEvent', inverse_of: :abuse_report
- validates :reporter, presence: true
- validates :user, presence: true
+ validates :reporter, presence: true, on: :create
+ validates :user, presence: true, on: :create
validates :message, presence: true
validates :category, presence: true
validates :user_id,
@@ -27,7 +29,7 @@ class AbuseReport < ApplicationRecord
message: ->(object, data) do
_('You have already reported this user')
end
- }
+ }, on: :create
validates :reported_from_url,
allow_blank: true,
@@ -45,6 +47,9 @@ class AbuseReport < ApplicationRecord
message: N_("exceeds the limit of %{count} links")
}
+ validates :mitigation_steps, length: { maximum: 1000 }, allow_blank: true
+ validates :evidence, json_schema: { filename: 'abuse_report_evidence' }, allow_blank: true
+
before_validation :filter_empty_strings_from_links_to_spam
validate :links_to_spam_contains_valid_urls
diff --git a/app/models/project_import_data.rb b/app/models/project_import_data.rb
index 3b514d5c5ff..7e0722ab68c 100644
--- a/app/models/project_import_data.rb
+++ b/app/models/project_import_data.rb
@@ -7,12 +7,12 @@ class ProjectImportData < ApplicationRecord
belongs_to :project, inverse_of: :import_data
attr_encrypted :credentials,
- key: Settings.attr_encrypted_db_key_base,
- marshal: true,
- encode: true,
- mode: :per_attribute_iv_and_salt,
- insecure_mode: true,
- algorithm: 'aes-256-cbc'
+ key: Settings.attr_encrypted_db_key_base,
+ marshal: true,
+ encode: true,
+ mode: :per_attribute_iv_and_salt,
+ insecure_mode: true,
+ algorithm: 'aes-256-cbc'
# NOTE
# We are serializing a project as `data` in an "unsafe" way here
diff --git a/app/models/project_team.rb b/app/models/project_team.rb
index dd200aec807..631797ee812 100644
--- a/app/models/project_team.rb
+++ b/app/models/project_team.rb
@@ -179,9 +179,11 @@ class ProjectTeam
#
# Returns a Hash mapping user ID -> maximum access level.
def max_member_access_for_user_ids(user_ids)
- Gitlab::SafeRequestLoader.execute(resource_key: project.max_member_access_for_resource_key(User),
- resource_ids: user_ids,
- default_value: Gitlab::Access::NO_ACCESS) do |user_ids|
+ Gitlab::SafeRequestLoader.execute(
+ resource_key: project.max_member_access_for_resource_key(User),
+ resource_ids: user_ids,
+ default_value: Gitlab::Access::NO_ACCESS
+ ) do |user_ids|
project.project_authorizations
.where(user: user_ids)
.group(:user_id)
@@ -202,9 +204,11 @@ class ProjectTeam
end
def contribution_check_for_user_ids(user_ids)
- Gitlab::SafeRequestLoader.execute(resource_key: "contribution_check_for_users:#{project.id}",
- resource_ids: user_ids,
- default_value: false) do |user_ids|
+ Gitlab::SafeRequestLoader.execute(
+ resource_key: "contribution_check_for_users:#{project.id}",
+ resource_ids: user_ids,
+ default_value: false
+ ) do |user_ids|
project.merge_requests
.merged
.where(author_id: user_ids, target_branch: project.default_branch.to_s)
diff --git a/app/models/prometheus_alert.rb b/app/models/prometheus_alert.rb
index 59440947d71..52fc0a9d1bb 100644
--- a/app/models/prometheus_alert.rb
+++ b/app/models/prometheus_alert.rb
@@ -25,7 +25,7 @@ class PrometheusAlert < ApplicationRecord
validates :environment, :project, :prometheus_metric, :threshold, :operator, presence: true
validates :runbook_url, length: { maximum: 255 }, allow_blank: true,
- addressable_url: { enforce_sanitization: true, ascii_only: true }
+ addressable_url: { enforce_sanitization: true, ascii_only: true }
validate :require_valid_environment_project!
validate :require_valid_metric_project!
diff --git a/app/models/release.rb b/app/models/release.rb
index 0f00732b62e..10eb022b08b 100644
--- a/app/models/release.rb
+++ b/app/models/release.rb
@@ -35,8 +35,10 @@ class Release < ApplicationRecord
scope :sorted, -> { order(released_at: :desc) }
scope :preloaded, -> {
- includes(:author, :evidences, :milestones, :links, :sorted_links,
- project: [:project_feature, :route, { namespace: :route }])
+ includes(
+ :author, :evidences, :milestones, :links, :sorted_links,
+ project: [:project_feature, :route, { namespace: :route }]
+ )
}
scope :with_milestones, -> { joins(:milestone_releases) }
scope :with_group_milestones, -> { joins(:milestones).where.not(milestones: { group_id: nil }) }
diff --git a/app/models/releases/source.rb b/app/models/releases/source.rb
index 44760541290..3ad7efcfcec 100644
--- a/app/models/releases/source.rb
+++ b/app/models/releases/source.rb
@@ -9,9 +9,7 @@ module Releases
class << self
def all(project, tag_name)
Gitlab::Workhorse::ARCHIVE_FORMATS.map do |format|
- Releases::Source.new(project: project,
- tag_name: tag_name,
- format: format)
+ Releases::Source.new(project: project, tag_name: tag_name, format: format)
end
end
end
@@ -19,9 +17,7 @@ module Releases
def url
Gitlab::Routing
.url_helpers
- .project_archive_url(project,
- id: File.join(tag_name, archive_prefix),
- format: format)
+ .project_archive_url(project, id: File.join(tag_name, archive_prefix), format: format)
end
def hook_attrs
diff --git a/app/models/remote_mirror.rb b/app/models/remote_mirror.rb
index b830cf313af..8b2f3bdcedf 100644
--- a/app/models/remote_mirror.rb
+++ b/app/models/remote_mirror.rb
@@ -11,12 +11,12 @@ class RemoteMirror < ApplicationRecord
UNPROTECTED_BACKOFF_DELAY = 5.minutes
attr_encrypted :credentials,
- key: Settings.attr_encrypted_db_key_base,
- marshal: true,
- encode: true,
- mode: :per_attribute_iv_and_salt,
- insecure_mode: true,
- algorithm: 'aes-256-cbc'
+ key: Settings.attr_encrypted_db_key_base,
+ marshal: true,
+ encode: true,
+ mode: :per_attribute_iv_and_salt,
+ insecure_mode: true,
+ algorithm: 'aes-256-cbc'
belongs_to :project, inverse_of: :remote_mirrors
@@ -31,10 +31,8 @@ class RemoteMirror < ApplicationRecord
scope :stuck, -> do
started
- .where('(last_update_started_at < ? AND last_update_at IS NOT NULL)',
- MAX_INCREMENTAL_RUNTIME.ago)
- .or(where('(last_update_started_at < ? AND last_update_at IS NULL)',
- MAX_FIRST_RUNTIME.ago))
+ .where('(last_update_started_at < ? AND last_update_at IS NOT NULL)', MAX_INCREMENTAL_RUNTIME.ago)
+ .or(where('(last_update_started_at < ? AND last_update_at IS NULL)', MAX_FIRST_RUNTIME.ago))
end
state_machine :update_status, initial: :none do
diff --git a/app/models/repository.rb b/app/models/repository.rb
index e942157993b..acb795f174d 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -880,10 +880,12 @@ class Repository
end
def merge(user, source_sha, merge_request, message)
- merge_to_branch(user,
- source_sha: source_sha,
- target_branch: merge_request.target_branch,
- message: message) do |commit_id|
+ merge_to_branch(
+ user,
+ source_sha: source_sha,
+ target_branch: merge_request.target_branch,
+ message: message
+ ) do |commit_id|
merge_request.update_and_mark_in_progress_merge_commit_sha(commit_id)
nil # Return value does not matter.
end
@@ -1136,10 +1138,13 @@ class Repository
end
def squash(user, merge_request, message)
- raw.squash(user, start_sha: merge_request.diff_start_sha,
- end_sha: merge_request.diff_head_sha,
- author: merge_request.author,
- message: message)
+ raw.squash(
+ user,
+ start_sha: merge_request.diff_start_sha,
+ end_sha: merge_request.diff_head_sha,
+ author: merge_request.author,
+ message: message
+ )
end
def submodule_links
@@ -1271,11 +1276,13 @@ class Repository
end
def initialize_raw_repository
- Gitlab::Git::Repository.new(shard,
- disk_path + '.git',
- repo_type.identifier_for_container(container),
- container.full_path,
- container: container)
+ Gitlab::Git::Repository.new(
+ shard,
+ disk_path + '.git',
+ repo_type.identifier_for_container(container),
+ container.full_path,
+ container: container
+ )
end
end
diff --git a/app/models/resource_timebox_event.rb b/app/models/resource_timebox_event.rb
index dddd4d0fe84..1cc77501d8d 100644
--- a/app/models/resource_timebox_event.rb
+++ b/app/models/resource_timebox_event.rb
@@ -34,8 +34,9 @@ class ResourceTimeboxEvent < ResourceEvent
case self
when ResourceMilestoneEvent
- Gitlab::UsageDataCounters::IssueActivityUniqueCounter.track_issue_milestone_changed_action(author: user,
- project: issue.project)
+ Gitlab::UsageDataCounters::IssueActivityUniqueCounter.track_issue_milestone_changed_action(
+ author: user, project: issue.project
+ )
else
# no-op
end
diff --git a/app/models/terraform/state.rb b/app/models/terraform/state.rb
index 93c128c989c..ecd3e27a9c4 100644
--- a/app/models/terraform/state.rb
+++ b/app/models/terraform/state.rb
@@ -28,7 +28,7 @@ module Terraform
validates :project_id, :name, presence: true
validates :uuid, presence: true, uniqueness: true, length: { is: UUID_LENGTH },
- format: { with: HEX_REGEXP, message: 'only allows hex characters' }
+ format: { with: HEX_REGEXP, message: 'only allows hex characters' }
attribute :uuid, default: -> { SecureRandom.hex(UUID_LENGTH / 2) }
diff --git a/app/models/time_tracking/timelog_category.rb b/app/models/time_tracking/timelog_category.rb
index 246e78f31cb..67565039acd 100644
--- a/app/models/time_tracking/timelog_category.rb
+++ b/app/models/time_tracking/timelog_category.rb
@@ -18,9 +18,9 @@ module TimeTracking
validates :description, length: { maximum: 1024 }
validates :color, color: true, allow_blank: false, length: { maximum: 7 }
validates :billing_rate,
- if: :billable?,
- presence: true,
- numericality: { greater_than: 0 }
+ if: :billable?,
+ presence: true,
+ numericality: { greater_than: 0 }
DEFAULT_COLOR = ::Gitlab::Color.of('#6699cc')
diff --git a/app/models/user.rb b/app/models/user.rb
index 1bccb5466dd..87e31f84839 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -216,8 +216,10 @@ class User < ApplicationRecord
has_many :releases, dependent: :nullify, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent
has_many :subscriptions, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :oauth_applications, class_name: 'Doorkeeper::Application', as: :owner, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
- has_many :abuse_reports, dependent: :destroy, foreign_key: :user_id # rubocop:disable Cop/ActiveRecordDependent
- has_many :reported_abuse_reports, dependent: :destroy, foreign_key: :reporter_id, class_name: "AbuseReport" # rubocop:disable Cop/ActiveRecordDependent
+ has_many :abuse_reports, dependent: :nullify, foreign_key: :user_id, inverse_of: :user # rubocop:disable Cop/ActiveRecordDependent
+ has_many :reported_abuse_reports, dependent: :nullify, foreign_key: :reporter_id, class_name: "AbuseReport", inverse_of: :reporter # rubocop:disable Cop/ActiveRecordDependent
+ has_many :assigned_abuse_reports, foreign_key: :assignee_id, class_name: "AbuseReport", inverse_of: :assignee
+ has_many :resolved_abuse_reports, foreign_key: :resolved_by_id, class_name: "AbuseReport", inverse_of: :resolved_by
has_many :spam_logs, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :abuse_trust_scores, class_name: 'Abuse::TrustScore', foreign_key: :user_id
has_many :builds, class_name: 'Ci::Build'
diff --git a/app/validators/json_schemas/abuse_report_evidence.json b/app/validators/json_schemas/abuse_report_evidence.json
new file mode 100644
index 00000000000..e00628d5704
--- /dev/null
+++ b/app/validators/json_schemas/abuse_report_evidence.json
@@ -0,0 +1,107 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "description": "Evidence to support an abuse report",
+ "type": "object",
+ "properties": {
+ "issues": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "integer"
+ },
+ "title": {
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "id",
+ "title",
+ "description"
+ ]
+ }
+ },
+ "snippets": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "integer"
+ },
+ "content": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "id",
+ "content"
+ ]
+ }
+ },
+ "notes": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "integer"
+ },
+ "content": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "id",
+ "content"
+ ]
+ }
+ },
+ "user": {
+ "type": "object",
+ "properties": {
+ "login_count": {
+ "type": "integer"
+ },
+ "account_age": {
+ "type": "integer"
+ },
+ "spam_score": {
+ "type": "number"
+ },
+ "telesign_score": {
+ "type": "number"
+ },
+ "arkos_score": {
+ "type": "number"
+ },
+ "pvs_score": {
+ "type": "number"
+ },
+ "product_coverage": {
+ "type": "number"
+ },
+ "virus_total_score": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "login_count",
+ "account_age",
+ "spam_score",
+ "telesign_score",
+ "arkos_score",
+ "pvs_score",
+ "product_coverage",
+ "virus_total_score"
+ ]
+ }
+ },
+ "required": [
+ "user"
+ ]
+}
diff --git a/app/views/clusters/clusters/_banner.html.haml b/app/views/clusters/clusters/_banner.html.haml
index 6461b71b10d..7d5d41c2851 100644
--- a/app/views/clusters/clusters/_banner.html.haml
+++ b/app/views/clusters/clusters/_banner.html.haml
@@ -8,12 +8,12 @@
= render Pajamas::AlertComponent.new(variant: :warning,
alert_options: { class: 'hidden js-cluster-api-unreachable' }) do |c|
- = c.body do
+ - c.with_body do
= s_('ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct.')
= render Pajamas::AlertComponent.new(variant: :warning,
alert_options: { class: 'hidden js-cluster-authentication-failure js-cluster-api-unreachable' }) do |c|
- = c.body do
+ - c.with_body do
= s_('ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid.')
.hidden.js-cluster-success.bs-callout.bs-callout-success{ role: 'alert' }
diff --git a/app/views/clusters/clusters/_deprecation_alert.html.haml b/app/views/clusters/clusters/_deprecation_alert.html.haml
index 0318c0f7dfa..4f35ba78cc6 100644
--- a/app/views/clusters/clusters/_deprecation_alert.html.haml
+++ b/app/views/clusters/clusters/_deprecation_alert.html.haml
@@ -1,5 +1,5 @@
= render Pajamas::AlertComponent.new(variant: :warning, dismissible: false, alert_options: { class: 'gl-mt-6 gl-mb-3' }) do |c|
- = c.body do
+ - c.with_body do
- link_start = ''.html_safe
- issue_link_start = link_start % { url: 'https://gitlab.com/gitlab-org/configure/general/-/issues/199' }
- docs_link_start = link_start % { url: help_page_path('user/clusters/agent/index.md') }
diff --git a/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml b/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml
index 40632e27fa7..08badbb4963 100644
--- a/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml
+++ b/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml
@@ -4,8 +4,8 @@
alert_options: { class: 'gcp-signup-offer',
data: { feature_id: Users::CalloutsHelper::GCP_SIGNUP_OFFER, dismiss_endpoint: callouts_path }},
close_button_options: { data: { track_action: 'click_dismiss', track_label: 'gcp_signup_offer_banner' }}) do |c|
- = c.body do
+ - c.with_body do
= s_('ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab\'s Google Kubernetes Engine Integration.').html_safe % { sign_up_link: link }
- = c.actions do
+ - c.with_actions do
= render Pajamas::ButtonComponent.new(variant: :confirm, href: 'https://cloud.google.com/partners/partnercredit/?pcn_code=0014M00001h35gDQAQ#contact-form', target: '_blank', button_options: { rel: 'noopener noreferrer', data: { track_action: 'click_button', track_label: 'gcp_signup_offer_banner' } }) do
= s_("ClusterIntegration|Apply for credit")
diff --git a/app/views/dashboard/projects/_blank_state_welcome.html.haml b/app/views/dashboard/projects/_blank_state_welcome.html.haml
index c5fdc31a775..2b13e2ba9a5 100644
--- a/app/views/dashboard/projects/_blank_state_welcome.html.haml
+++ b/app/views/dashboard/projects/_blank_state_welcome.html.haml
@@ -12,7 +12,7 @@
= _('Projects are where you store your code, access issues, wiki and other features of GitLab.')
- else
= render Pajamas::AlertComponent.new(variant: :info, alert_options: { class: 'gl-mb-5 gl-w-full' }) do |c|
- = c.body do
+ - c.with_body do
= _("You see projects here when you're added to a group or project.").html_safe
- if current_user.can_create_group?
diff --git a/app/views/devise/sessions/_new_ldap.html.haml b/app/views/devise/sessions/_new_ldap.html.haml
index fb5a57b509c..5fa9b3272f0 100644
--- a/app/views/devise/sessions/_new_ldap.html.haml
+++ b/app/views/devise/sessions/_new_ldap.html.haml
@@ -12,7 +12,7 @@
- if render_remember_me
.gl-px-5
= render Pajamas::CheckboxTagComponent.new(name: 'remember_me') do |c|
- = c.label do
+ - c.with_label do
= _('Remember me')
.submit-container.move-submit-down.gl-px-5.gl-pb-5
diff --git a/app/views/devise/shared/_error_messages.html.haml b/app/views/devise/shared/_error_messages.html.haml
index b7589a4460e..caebda72b9c 100644
--- a/app/views/devise/shared/_error_messages.html.haml
+++ b/app/views/devise/shared/_error_messages.html.haml
@@ -3,7 +3,7 @@
variant: :danger,
dismissible: false,
alert_options: { id: 'error_explanation', class: 'gl-mb-3'}) do |c|
- = c.body do
+ - c.with_body do
%ul.gl-pl-4
- resource.errors.full_messages.each do |message|
%li= message
diff --git a/app/views/devise/shared/_omniauth_box.html.haml b/app/views/devise/shared/_omniauth_box.html.haml
index 14a9bde2d9e..8f2c2c58790 100644
--- a/app/views/devise/shared/_omniauth_box.html.haml
+++ b/app/views/devise/shared/_omniauth_box.html.haml
@@ -18,5 +18,5 @@
= label_for_provider(provider)
- if render_remember_me
= render Pajamas::CheckboxTagComponent.new(name: 'remember_me_omniauth', value: nil) do |c|
- = c.label do
+ - c.with_label do
= _('Remember me')
diff --git a/app/views/explore/projects/_filter.html.haml b/app/views/explore/projects/_filter.html.haml
index e49b3eb7781..88d57ed7e33 100644
--- a/app/views/explore/projects/_filter.html.haml
+++ b/app/views/explore/projects/_filter.html.haml
@@ -3,5 +3,5 @@
- if current_user
- unless has_label
- %span.gl-float-left= _("Visibility:")
+ %span.gl-float-left.gl-white-space-nowrap= _("Visibility:")
= gl_redirect_listbox_tag(projects_filter_items, selected, class: 'gl-ml-3', data: { placement: 'right' })
diff --git a/app/views/import/shared/_errors.html.haml b/app/views/import/shared/_errors.html.haml
index 2dbb54a9a0e..760715b56ea 100644
--- a/app/views/import/shared/_errors.html.haml
+++ b/app/views/import/shared/_errors.html.haml
@@ -2,6 +2,6 @@
= render Pajamas::AlertComponent.new(variant: :danger,
dismissible: false,
alert_options: { class: 'gl-mb-5' }) do |c|
- = c.body do
+ - c.with_body do
- @errors.each do |error|
= error
diff --git a/app/views/layouts/header/_registration_enabled_callout.html.haml b/app/views/layouts/header/_registration_enabled_callout.html.haml
index 5c70136a932..ee4644e9ff0 100644
--- a/app/views/layouts/header/_registration_enabled_callout.html.haml
+++ b/app/views/layouts/header/_registration_enabled_callout.html.haml
@@ -6,9 +6,9 @@
data: { feature_id: Users::CalloutsHelper::REGISTRATION_ENABLED_CALLOUT,
dismiss_endpoint: callouts_path }},
close_button_options: { data: { testid: 'close-registration-enabled-callout' }}) do |c|
- = c.body do
+ - c.with_body do
= _("Your GitLab instance allows anyone to register for an account, which is a security risk on public-facing GitLab instances. You should deactivate new sign ups if public users aren't expected to register for an account.")
- = c.actions do
+ - c.with_actions do
= render Pajamas::ButtonComponent.new(variant: :confirm, href: general_admin_application_settings_path(anchor: 'js-signup-settings')) do
= _('Deactivate')
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-close gl-ml-3'}) do
diff --git a/app/views/layouts/terms.html.haml b/app/views/layouts/terms.html.haml
index 71c622d7a62..9a50e3e2eb2 100644
--- a/app/views/layouts/terms.html.haml
+++ b/app/views/layouts/terms.html.haml
@@ -17,9 +17,9 @@
%div{ class: "#{container_class} limit-container-width" }
.content{ id: "content-body" }
= render Pajamas::CardComponent.new do |c|
- = c.header do
+ - c.with_header do
= brand_header_logo({add_gitlab_black_text: true})
- = c.body do
+ - c.with_body do
- if header_link?(:user_dropdown)
.navbar-collapse
%ul.nav.navbar-nav
diff --git a/app/views/profiles/accounts/show.html.haml b/app/views/profiles/accounts/show.html.haml
index ea8d6b7fda2..91a54f15305 100644
--- a/app/views/profiles/accounts/show.html.haml
+++ b/app/views/profiles/accounts/show.html.haml
@@ -4,14 +4,14 @@
- if current_user.ldap_user?
= render Pajamas::AlertComponent.new(alert_options: { class: 'gl-my-5' },
dismissible: false) do |c|
- = c.body do
+ - c.with_body do
= s_('Profiles|Some options are unavailable for LDAP accounts')
- if params[:two_factor_auth_enabled_successfully]
= render Pajamas::AlertComponent.new(variant: :success,
alert_options: { class: 'gl-my-5' },
close_button_options: { class: 'js-close-2fa-enabled-success-alert' }) do |c|
- = c.body do
+ - c.with_body do
= html_escape(_('You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}.')) % { anchorOpen: ''.html_safe % { href: help_page_path('user/profile/account/two_factor_authentication', anchor: 'generate-new-recovery-codes-using-ssh') }, anchorClose: ''.html_safe }
.row.gl-mt-3.js-search-settings-section
diff --git a/app/views/profiles/active_sessions/index.html.haml b/app/views/profiles/active_sessions/index.html.haml
index 54736153223..1952655937e 100644
--- a/app/views/profiles/active_sessions/index.html.haml
+++ b/app/views/profiles/active_sessions/index.html.haml
@@ -11,6 +11,6 @@
.gl-mb-3
= render Pajamas::CardComponent.new(card_options: { class: 'gl-border-0' }, body_options: { class: 'gl-p-0' }) do |c|
- - c.body do
+ - c.with_body do
%ul.list-group.list-group-flush
= render partial: 'profiles/active_sessions/active_session', collection: @sessions
diff --git a/app/views/profiles/chat_names/new.html.haml b/app/views/profiles/chat_names/new.html.haml
index bc30ccc5821..b0a694f9bc6 100644
--- a/app/views/profiles/chat_names/new.html.haml
+++ b/app/views/profiles/chat_names/new.html.haml
@@ -3,9 +3,9 @@
%main{ role: 'main' }
.gl-max-w-80.gl-mx-auto.gl-mt-6
= render Pajamas::CardComponent.new do |c|
- - c.header do
+ - c.with_header do
%h4.gl-m-0= sprintf(s_('Integrations|Authorize %{integration_name} (%{user}) to use your account?'), { user: @chat_name_params[:chat_name], integration_name: @integration_name })
- - c.body do
+ - c.with_body do
%p
= sprintf(s_('Integrations|An application called %{integration_name} is requesting access to your GitLab account. This application was created by GitLab Inc.'), { integration_name: @integration_name })
%p
@@ -16,7 +16,7 @@
%li= s_('SlackIntegration|Run ChatOps jobs.')
%p.gl-mb-0
= s_("SlackIntegration|You don't have to reauthorize this application if the permission scope changes in future releases.")
- - c.footer do
+ - c.with_footer do
.gl-display-flex
= form_tag profile_chat_names_path, method: :post do
= hidden_field_tag :token, @chat_name_token.token
diff --git a/app/views/profiles/keys/_key_details.html.haml b/app/views/profiles/keys/_key_details.html.haml
index 3c05502be57..4f3d97fb90c 100644
--- a/app/views/profiles/keys/_key_details.html.haml
+++ b/app/views/profiles/keys/_key_details.html.haml
@@ -2,9 +2,9 @@
.row.gl-mt-3
.col-md-4
= render Pajamas::CardComponent.new(body_options: { class: 'gl-py-0'}) do |c|
- - c.header do
+ - c.with_header do
= _('SSH Key')
- - c.body do
+ - c.with_body do
%ul.content-list
%li
%span.light= _('Title:')
@@ -27,9 +27,9 @@
%pre.well-pre
= @key.key
= render Pajamas::CardComponent.new(body_options: { class: 'gl-py-0'}) do |c|
- - c.header do
+ - c.with_header do
= _('Fingerprints')
- - c.body do
+ - c.with_body do
%ul.content-list
%li
%span.light= 'MD5:'
diff --git a/app/views/profiles/notifications/show.html.haml b/app/views/profiles/notifications/show.html.haml
index a632c450eda..06d37787d2e 100644
--- a/app/views/profiles/notifications/show.html.haml
+++ b/app/views/profiles/notifications/show.html.haml
@@ -5,7 +5,7 @@
%div
- if @user.errors.any?
= render Pajamas::AlertComponent.new(variant: :danger) do |c|
- = c.body do
+ - c.with_body do
%ul
- @user.errors.full_messages.each do |msg|
%li= msg
diff --git a/app/views/profiles/two_factor_auths/show.html.haml b/app/views/profiles/two_factor_auths/show.html.haml
index 9cc7f6bdd49..461164e1ae9 100644
--- a/app/views/profiles/two_factor_auths/show.html.haml
+++ b/app/views/profiles/two_factor_auths/show.html.haml
@@ -24,7 +24,7 @@
= raw @qr_code
.col-md-8
= render Pajamas::CardComponent.new do |c|
- - c.body do
+ - c.with_body do
%p.gl-mt-0.gl-mb-3.gl-font-weight-bold
= _("Can't scan the code?")
%p.gl-mt-0.gl-mb-3
@@ -42,7 +42,7 @@
variant: :danger,
alert_options: { class: 'gl-mb-3' },
dismissible: false) do |c|
- = c.body do
+ - c.with_body do
= link_to _('Try the troubleshooting steps here.'), help_page_path('user/profile/account/two_factor_authentication.md', anchor: 'troubleshooting'), target: '_blank', rel: 'noopener noreferrer'
- if current_password_required?
@@ -130,7 +130,7 @@
variant: :danger,
alert_options: { class: 'gl-mb-3' },
dismissible: false) do |c|
- = c.body do
+ - c.with_body do
= link_to _('Try the troubleshooting steps here.'), help_page_path('user/profile/account/two_factor_authentication.md', anchor: 'troubleshooting'), target: '_blank', rel: 'noopener noreferrer'
.js-manage-two-factor-form{ data: { current_password_required: current_password_required?.to_s, profile_two_factor_auth_path: profile_two_factor_auth_path, profile_two_factor_auth_method: 'delete', codes_profile_two_factor_auth_path: codes_profile_two_factor_auth_path, codes_profile_two_factor_auth_method: 'post' } }
- else
diff --git a/app/views/projects/mirrors/_branch_filter.html.haml b/app/views/projects/mirrors/_branch_filter.html.haml
index b9db9898d49..49b0f8c39c8 100644
--- a/app/views/projects/mirrors/_branch_filter.html.haml
+++ b/app/views/projects/mirrors/_branch_filter.html.haml
@@ -1,6 +1,9 @@
-.form-check.gl-mb-3
- = check_box_tag :only_protected_branches, '1', false, class: 'js-mirror-protected form-check-input'
- = label_tag :only_protected_branches, _('Mirror only protected branches'), class: 'form-check-label'
- .form-text.text-muted
- = _('If enabled, only protected branches will be mirrored.')
- = link_to _('Learn more.'), help_page_path('user/project/repository/mirror/index.md', anchor: 'mirror-only-protected-branches'), target: '_blank', rel: 'noopener noreferrer'
+.form-group
+ = render Pajamas::CheckboxTagComponent.new(name: :only_protected_branches,
+ checkbox_options: { class: 'js-mirror-protected' },
+ label_options: { class: 'gl-mb-0!' }) do |c|
+ = c.label do
+ = _('Mirror only protected branches')
+ = c.help_text do
+ = _('If enabled, only protected branches will be mirrored.')
+ = link_to _('Learn more.'), help_page_path('user/project/repository/mirror/index.md', anchor: 'mirror-only-protected-branches'), target: '_blank', rel: 'noopener noreferrer'
diff --git a/app/views/projects/settings/operations/_grafana_integration.html.haml b/app/views/projects/settings/operations/_grafana_integration.html.haml
deleted file mode 100644
index 69e42a6c4fb..00000000000
--- a/app/views/projects/settings/operations/_grafana_integration.html.haml
+++ /dev/null
@@ -1,2 +0,0 @@
-.js-grafana-integration{ data: { operations_settings_endpoint: project_settings_operations_path(@project),
- grafana_integration: { url: grafana_integration_url, token: grafana_integration_masked_token, enabled: grafana_integration_enabled?.to_s } } }
diff --git a/app/views/projects/settings/operations/_metrics_dashboard.html.haml b/app/views/projects/settings/operations/_metrics_dashboard.html.haml
deleted file mode 100644
index 056d3e8102b..00000000000
--- a/app/views/projects/settings/operations/_metrics_dashboard.html.haml
+++ /dev/null
@@ -1,5 +0,0 @@
-.js-operation-settings{ data: { operations_settings_endpoint: project_settings_operations_path(@project),
- help_page: help_page_path('operations/metrics/dashboards/settings'),
- external_dashboard: { url: metrics_external_dashboard_url,
- help_page: help_page_path('operations/metrics/dashboards/settings') },
- dashboard_timezone: { setting: metrics_dashboard_timezone.upcase } } }
diff --git a/app/views/projects/settings/operations/show.html.haml b/app/views/projects/settings/operations/show.html.haml
index d44ebf1eb83..93ab98c1472 100644
--- a/app/views/projects/settings/operations/show.html.haml
+++ b/app/views/projects/settings/operations/show.html.haml
@@ -2,14 +2,7 @@
- breadcrumb_title _('Monitor Settings')
- @force_desktop_expanded_sidebar = true
-- if Feature.disabled?(:remove_monitor_metrics)
- = render 'projects/settings/operations/metrics_dashboard'
-
= render 'projects/settings/operations/error_tracking'
= render 'projects/settings/operations/alert_management'
= render 'projects/settings/operations/incidents'
-
-- if Feature.disabled?(:remove_monitor_metrics)
- = render 'projects/settings/operations/grafana_integration'
-
= render_if_exists 'projects/settings/operations/status_page'
diff --git a/app/views/protected_branches/shared/_create_protected_branch.html.haml b/app/views/protected_branches/shared/_create_protected_branch.html.haml
index 9bc224b2e78..62cf81a59d4 100644
--- a/app/views/protected_branches/shared/_create_protected_branch.html.haml
+++ b/app/views/protected_branches/shared/_create_protected_branch.html.haml
@@ -1,9 +1,9 @@
= gitlab_ui_form_for [protected_branch_entity, @protected_branch], html: { class: 'new-protected-branch js-new-protected-branch' } do |f|
%input{ type: 'hidden', name: 'update_section', value: 'js-protected-branches-settings' }
= render Pajamas::CardComponent.new(card_options: { class: "gl-mb-5" }) do |c|
- - c.header do
+ - c.with_header do
= s_("ProtectedBranch|Protect a branch")
- - c.body do
+ - c.with_body do
= form_errors(@protected_branch)
.form-group.row
= f.label :name, s_('ProtectedBranch|Branch:'), class: 'col-sm-12'
@@ -38,7 +38,7 @@
- force_push_link_start = ''.html_safe % { url: force_push_docs_url }
= (s_("ProtectedBranch|Allow all users with push access to %{tag_start}force push%{tag_end}.") % { tag_start: force_push_link_start, tag_end: '' }).html_safe
= render_if_exists 'protected_branches/ee/code_owner_approval_form', f: f, protected_branch_entity: protected_branch_entity
- - c.footer do
+ - c.with_footer do
= f.submit s_('ProtectedBranch|Protect'), disabled: true, data: { qa_selector: 'protect_button' }, pajamas_button: true
.js-alert-protected-branch-created-container.gl-mb-5
diff --git a/app/views/registrations/welcome/show.html.haml b/app/views/registrations/welcome/show.html.haml
index 6c8ab5654a0..d59ad342972 100644
--- a/app/views/registrations/welcome/show.html.haml
+++ b/app/views/registrations/welcome/show.html.haml
@@ -23,7 +23,7 @@
'aria-live' => 'assertive',
data: { testid: 'welcome-form' } }) do |f|
= render Pajamas::CardComponent.new do |c|
- - c.body do
+ - c.with_body do
.devise-errors
= render 'devise/shared/error_messages', resource: current_user
.row
diff --git a/config/feature_flags/development/fix_dora_deployment_frequency_calculation.yml b/config/feature_flags/development/add_validation_for_push_rules.yml
similarity index 52%
rename from config/feature_flags/development/fix_dora_deployment_frequency_calculation.yml
rename to config/feature_flags/development/add_validation_for_push_rules.yml
index efc68c28eab..c1cb4b4f601 100644
--- a/config/feature_flags/development/fix_dora_deployment_frequency_calculation.yml
+++ b/config/feature_flags/development/add_validation_for_push_rules.yml
@@ -1,8 +1,8 @@
---
-name: fix_dora_deployment_frequency_calculation
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/116644
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/404565
-milestone: '15.11'
+name: add_validation_for_push_rules
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121030
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/411901
+milestone: '16.1'
type: development
-group: group::optimize
-default_enabled: true
+group: group::source code
+default_enabled: false
diff --git a/config/feature_flags/development/environment_settings_to_graphql.yml b/config/feature_flags/development/environment_settings_to_graphql.yml
new file mode 100644
index 00000000000..89da0c73324
--- /dev/null
+++ b/config/feature_flags/development/environment_settings_to_graphql.yml
@@ -0,0 +1,8 @@
+---
+name: environment_settings_to_graphql
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121091
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/412332
+milestone: '16.1'
+type: development
+group: group::environments
+default_enabled: false
diff --git a/danger/roulette/Dangerfile b/danger/roulette/Dangerfile
index 5b865498651..27c33a0c144 100644
--- a/danger/roulette/Dangerfile
+++ b/danger/roulette/Dangerfile
@@ -55,7 +55,7 @@ end
OPTIONAL_REVIEW_TEMPLATE = '%{role} review is optional for %{category}'
NOT_AVAILABLE_TEMPLATES = {
default: 'No %{role} available',
- product_intelligence: group_not_available_template('#g_analyze_analytics_instrumentation', '@gitlab-org/analytics-section/product-intelligence/engineers'),
+ analytics_instrumentation: group_not_available_template('#g_analyze_analytics_instrumentation', '@gitlab-org/analytics-section/analytics-instrumentation/engineers'),
import_integrate_be: group_not_available_template('#g_manage_import_and_integrate', '@gitlab-org/manage/import-and-integrate'),
import_integrate_fe: group_not_available_template('#g_manage_import_and_integrate', '@gitlab-org/manage/import-and-integrate')
}.freeze
diff --git a/db/migrate/20230517182802_add_fields_to_abuse_reports.rb b/db/migrate/20230517182802_add_fields_to_abuse_reports.rb
new file mode 100644
index 00000000000..dc83e4a1879
--- /dev/null
+++ b/db/migrate/20230517182802_add_fields_to_abuse_reports.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+class AddFieldsToAbuseReports < Gitlab::Database::Migration[2.1]
+ RESOLVED_BY_INDEX = 'index_abuse_reports_on_resolved_by_id'
+ ASSIGNEE_INDEX = 'index_abuse_reports_on_assignee_id'
+
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ add_column :abuse_reports, :resolved_by_id, :int, null: true
+ add_column :abuse_reports, :assignee_id, :int, null: true
+ add_column :abuse_reports, :mitigation_steps, :text, null: true
+ add_column :abuse_reports, :evidence, :jsonb, null: true
+ end
+
+ add_text_limit :abuse_reports, :mitigation_steps, 1000
+ add_concurrent_index :abuse_reports, :resolved_by_id, name: RESOLVED_BY_INDEX
+ add_concurrent_index :abuse_reports, :assignee_id, name: ASSIGNEE_INDEX
+ end
+
+ def down
+ change_table :abuse_reports do |t|
+ t.remove :resolved_by_id
+ t.remove :assignee_id
+ t.remove :mitigation_steps
+ t.remove :evidence
+ end
+ end
+end
diff --git a/db/migrate/20230517182958_add_foreign_key_constraints_to_abuse_reports.rb b/db/migrate/20230517182958_add_foreign_key_constraints_to_abuse_reports.rb
new file mode 100644
index 00000000000..17507c3ad46
--- /dev/null
+++ b/db/migrate/20230517182958_add_foreign_key_constraints_to_abuse_reports.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class AddForeignKeyConstraintsToAbuseReports < Gitlab::Database::Migration[2.1]
+ disable_ddl_transaction!
+
+ def up
+ return if foreign_key_exists?(:abuse_reports, column: :resolved_by_id)
+
+ add_concurrent_foreign_key :abuse_reports, :users,
+ column: :resolved_by_id,
+ null: true,
+ on_delete: :nullify
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key_if_exists :abuse_reports, column: :resolved_by_id
+ end
+ end
+end
diff --git a/db/migrate/20230517183403_add_foreign_key_to_abuse_reports_for_assignee.rb b/db/migrate/20230517183403_add_foreign_key_to_abuse_reports_for_assignee.rb
new file mode 100644
index 00000000000..d30133fb3a6
--- /dev/null
+++ b/db/migrate/20230517183403_add_foreign_key_to_abuse_reports_for_assignee.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class AddForeignKeyToAbuseReportsForAssignee < Gitlab::Database::Migration[2.1]
+ disable_ddl_transaction!
+
+ def up
+ return if foreign_key_exists?(:abuse_reports, column: :assignee_id)
+
+ add_concurrent_foreign_key :abuse_reports, :users,
+ column: :assignee_id,
+ null: true,
+ on_delete: :nullify
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key_if_exists :abuse_reports, column: :assignee_id
+ end
+ end
+end
diff --git a/db/migrate/20230523073455_add_new_async_index_table_name_length_constraint.rb b/db/migrate/20230523073455_add_new_async_index_table_name_length_constraint.rb
new file mode 100644
index 00000000000..96f3cc7372b
--- /dev/null
+++ b/db/migrate/20230523073455_add_new_async_index_table_name_length_constraint.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddNewAsyncIndexTableNameLengthConstraint < Gitlab::Database::Migration[2.1]
+ disable_ddl_transaction!
+
+ CONSTRAINT_NAME = 'check_schema_and_name_length'
+
+ def up
+ add_text_limit :postgres_async_indexes, :table_name, 127, constraint_name: CONSTRAINT_NAME, validate: false
+ end
+
+ def down
+ remove_text_limit :postgres_async_indexes, :table_name, constraint_name: CONSTRAINT_NAME
+ end
+end
diff --git a/db/migrate/20230523074248_validate_async_index_table_name_length_constraint.rb b/db/migrate/20230523074248_validate_async_index_table_name_length_constraint.rb
new file mode 100644
index 00000000000..5b7d74d7db9
--- /dev/null
+++ b/db/migrate/20230523074248_validate_async_index_table_name_length_constraint.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class ValidateAsyncIndexTableNameLengthConstraint < Gitlab::Database::Migration[2.1]
+ disable_ddl_transaction!
+
+ def up
+ validate_text_limit :postgres_async_indexes, :table_name, constraint_name: 'check_schema_and_name_length'
+ end
+
+ def down
+ # no-op because we cannot invalidate a constraint
+ end
+end
diff --git a/db/migrate/20230523074517_remove_old_async_index_table_name_length_constraint.rb b/db/migrate/20230523074517_remove_old_async_index_table_name_length_constraint.rb
new file mode 100644
index 00000000000..4d43cbdd032
--- /dev/null
+++ b/db/migrate/20230523074517_remove_old_async_index_table_name_length_constraint.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class RemoveOldAsyncIndexTableNameLengthConstraint < Gitlab::Database::Migration[2.1]
+ disable_ddl_transaction!
+
+ OLD_LENGTH_LIMIT = 63
+
+ def up
+ remove_text_limit :postgres_async_indexes, :table_name
+ end
+
+ def down
+ # Remove items that might break the old length validation. (unlikely to happen)
+ define_batchable_model('postgres_async_indexes').each_batch do |indexes|
+ indexes.where('CHAR_LENGTH(table_name) > ?', OLD_LENGTH_LIMIT).delete_all
+ end
+
+ add_text_limit :postgres_async_indexes, :table_name, OLD_LENGTH_LIMIT
+ end
+end
diff --git a/db/schema_migrations/20230517182802 b/db/schema_migrations/20230517182802
new file mode 100644
index 00000000000..e9ef71cf8bc
--- /dev/null
+++ b/db/schema_migrations/20230517182802
@@ -0,0 +1 @@
+8cd0b7369ad654e72fb12b9ae0d54cb38ada4b24a20358541dc5ab18ae60605c
\ No newline at end of file
diff --git a/db/schema_migrations/20230517182958 b/db/schema_migrations/20230517182958
new file mode 100644
index 00000000000..769fceffb75
--- /dev/null
+++ b/db/schema_migrations/20230517182958
@@ -0,0 +1 @@
+7a34b874349603c65c5ad8d71033a8ec23e7253c51bef20314a5c45d8da9903f
\ No newline at end of file
diff --git a/db/schema_migrations/20230517183403 b/db/schema_migrations/20230517183403
new file mode 100644
index 00000000000..1a4eed8c669
--- /dev/null
+++ b/db/schema_migrations/20230517183403
@@ -0,0 +1 @@
+7169d207128db503be38e1106f63a7c2e752ceacbfba93142a731267ce0fa0fe
\ No newline at end of file
diff --git a/db/schema_migrations/20230523073455 b/db/schema_migrations/20230523073455
new file mode 100644
index 00000000000..b1f55a3744b
--- /dev/null
+++ b/db/schema_migrations/20230523073455
@@ -0,0 +1 @@
+45f116be064d575bba2acab71458a89dbe5332c3cfb4544eb51638bf86081123
\ No newline at end of file
diff --git a/db/schema_migrations/20230523074248 b/db/schema_migrations/20230523074248
new file mode 100644
index 00000000000..29b21d2fcf7
--- /dev/null
+++ b/db/schema_migrations/20230523074248
@@ -0,0 +1 @@
+a9408102327280918366975b599985f3e382ebd493267fd010ad2dcbe6140eb3
\ No newline at end of file
diff --git a/db/schema_migrations/20230523074517 b/db/schema_migrations/20230523074517
new file mode 100644
index 00000000000..e6017c55df3
--- /dev/null
+++ b/db/schema_migrations/20230523074517
@@ -0,0 +1 @@
+662b78b3f796cec08f325ec71389bdaf9efa0695b6bfe224b18295175f1383bf
\ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index c117d095de4..7fee4c30bcc 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -10793,9 +10793,14 @@ CREATE TABLE abuse_reports (
status smallint DEFAULT 1 NOT NULL,
resolved_at timestamp with time zone,
screenshot text,
+ resolved_by_id integer,
+ assignee_id integer,
+ mitigation_steps text,
+ evidence jsonb,
CONSTRAINT abuse_reports_links_to_spam_length_check CHECK ((cardinality(links_to_spam) <= 20)),
CONSTRAINT check_4b0a5120e0 CHECK ((char_length(screenshot) <= 255)),
- CONSTRAINT check_ab1260fa6c CHECK ((char_length(reported_from_url) <= 512))
+ CONSTRAINT check_ab1260fa6c CHECK ((char_length(reported_from_url) <= 512)),
+ CONSTRAINT check_f3c0947a2d CHECK ((char_length(mitigation_steps) <= 1000))
);
CREATE SEQUENCE abuse_reports_id_seq
@@ -20324,7 +20329,7 @@ CREATE TABLE postgres_async_indexes (
CONSTRAINT check_083b21157b CHECK ((char_length(definition) <= 2048)),
CONSTRAINT check_45dc23c315 CHECK ((char_length(last_error) <= 10000)),
CONSTRAINT check_b732c6cd1d CHECK ((char_length(name) <= 63)),
- CONSTRAINT check_e64ff4359e CHECK ((char_length(table_name) <= 63))
+ CONSTRAINT check_schema_and_name_length CHECK ((char_length(table_name) <= 127))
);
CREATE SEQUENCE postgres_async_indexes_id_seq
@@ -29645,6 +29650,10 @@ CREATE INDEX index_abuse_report_events_on_abuse_report_id ON abuse_report_events
CREATE INDEX index_abuse_report_events_on_user_id ON abuse_report_events USING btree (user_id);
+CREATE INDEX index_abuse_reports_on_assignee_id ON abuse_reports USING btree (assignee_id);
+
+CREATE INDEX index_abuse_reports_on_resolved_by_id ON abuse_reports USING btree (resolved_by_id);
+
CREATE INDEX index_abuse_reports_on_status_and_created_at ON abuse_reports USING btree (status, created_at);
CREATE INDEX index_abuse_reports_on_status_and_id ON abuse_reports USING btree (status, id);
@@ -34902,6 +34911,9 @@ ALTER TABLE ONLY bulk_import_export_uploads
ALTER TABLE ONLY ci_pipelines
ADD CONSTRAINT fk_3d34ab2e06 FOREIGN KEY (pipeline_schedule_id) REFERENCES ci_pipeline_schedules(id) ON DELETE SET NULL;
+ALTER TABLE ONLY abuse_reports
+ ADD CONSTRAINT fk_3fe6467b93 FOREIGN KEY (assignee_id) REFERENCES users(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY protected_environment_approval_rules
ADD CONSTRAINT fk_405568b491 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
@@ -35616,6 +35628,9 @@ ALTER TABLE ONLY vulnerability_external_issue_links
ALTER TABLE ONLY epics
ADD CONSTRAINT fk_f081aa4489 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY abuse_reports
+ ADD CONSTRAINT fk_f10de8b524 FOREIGN KEY (resolved_by_id) REFERENCES users(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY boards
ADD CONSTRAINT fk_f15266b5f9 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
diff --git a/doc/administration/monitoring/prometheus/gitlab_metrics.md b/doc/administration/monitoring/prometheus/gitlab_metrics.md
index f92b408323c..f8cab0c605e 100644
--- a/doc/administration/monitoring/prometheus/gitlab_metrics.md
+++ b/doc/administration/monitoring/prometheus/gitlab_metrics.md
@@ -147,9 +147,9 @@ The following metrics are available:
| `service_desk_thank_you_email` | Counter | 14.0 | Total number of email responses to new Service Desk emails | |
| `service_desk_new_note_email` | Counter | 14.0 | Total number of email notifications on new Service Desk comment | |
| `email_receiver_error` | Counter | 14.1 | Total number of errors when processing incoming emails | |
-| `gitlab_snowplow_events_total` | Counter | 14.1 | Total number of GitLab Snowplow product intelligence events emitted | |
-| `gitlab_snowplow_failed_events_total` | Counter | 14.1 | Total number of GitLab Snowplow product intelligence events emission failures | |
-| `gitlab_snowplow_successful_events_total` | Counter | 14.1 | Total number of GitLab Snowplow product intelligence events emission successes | |
+| `gitlab_snowplow_events_total` | Counter | 14.1 | Total number of GitLab Snowplow Analytics Instrumentation events emitted | |
+| `gitlab_snowplow_failed_events_total` | Counter | 14.1 | Total number of GitLab Snowplow Analytics Instrumentation events emission failures | |
+| `gitlab_snowplow_successful_events_total` | Counter | 14.1 | Total number of GitLab Snowplow Analytics Instrumentation events emission successes | |
| `gitlab_ci_build_trace_errors_total` | Counter | 14.4 | Total amount of different error types on a build trace | `error_reason` |
| `gitlab_presentable_object_cacheless_render_real_duration_seconds` | Histogram | 15.3 | Duration of real time spent caching and representing specific web request objects | `controller`, `action` |
| `cached_object_operations_total` | Counter | 15.3 | Total number of objects cached for specific web requests | `controller`, `action` |
diff --git a/doc/architecture/blueprints/clickhouse_ingestion_pipeline/index.md b/doc/architecture/blueprints/clickhouse_ingestion_pipeline/index.md
index 94714e7b245..6645f390fd1 100644
--- a/doc/architecture/blueprints/clickhouse_ingestion_pipeline/index.md
+++ b/doc/architecture/blueprints/clickhouse_ingestion_pipeline/index.md
@@ -95,9 +95,9 @@ The following case-studies describe how each group intends to solve the underlyi
- In addition, [ClickHouse: Investigate client-side buffering to batch writes into ClickHouse](https://gitlab.com/gitlab-org/opstrace/opstrace/-/issues/2044) talks about their experimentation with using application-local queueing/batching to work around the problems mentioned above.
-- ~"group::product intelligence" has been working on building our analytics offering and recently looking at building and/or improving parts of the system.
+- ~"group::analytics instrumentation" has been working on building our analytics offering and recently looking at building and/or improving parts of the system.
- - [Product Analytics Collector Component](https://gitlab.com/groups/gitlab-org/-/epics/9346) talks about replacing Jitsu with Snowplow for collecting and processing tracking events. For more details of the proposal, see [Jitsu replacement](https://gitlab.com/gitlab-org/analytics-section/product-intelligence/proposals/-/blob/62d332baf5701810d9e7a0b2c00df18431e82f22/doc/jitsu_replacement.md).
+ - [Product Analytics Collector Component](https://gitlab.com/groups/gitlab-org/-/epics/9346) talks about replacing Jitsu with Snowplow for collecting and processing tracking events. For more details of the proposal, see [Jitsu replacement](https://gitlab.com/gitlab-org/analytics-section/analytics-instrumentation/proposals/-/blob/62d332baf5701810d9e7a0b2c00df18431e82f22/doc/jitsu_replacement.md).
- The initial design was prototyped with [Snowplow as Jitsu Replacement PoC](https://gitlab.com/gitlab-org/analytics-section/product-analytics/devkit/-/merge_requests/37).
diff --git a/doc/development/code_review.md b/doc/development/code_review.md
index 02f187d62c8..97b112c19d9 100644
--- a/doc/development/code_review.md
+++ b/doc/development/code_review.md
@@ -166,7 +166,7 @@ with [domain expertise](#domain-experts).
| End-to-end **and** non-end-to-end changes (*4*) | [Software Engineer in Test](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors). |
| Only End-to-end changes (*4*) **or** if the MR author is a [Software Engineer in Test](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors) | [Quality maintainer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_maintainers_qa). |
| A new or updated [application limit](https://about.gitlab.com/handbook/product/product-processes/#introducing-application-limits) | [Product manager](https://about.gitlab.com/company/team/). |
-| Analytics Instrumentation (telemetry or analytics) changes | [Analytics Instrumentation engineer](https://gitlab.com/gitlab-org/analytics-section/product-intelligence/engineers). |
+| Analytics Instrumentation (telemetry or analytics) changes | [Analytics Instrumentation engineer](https://gitlab.com/gitlab-org/analytics-section/analytics-instrumentation/engineers). |
| An addition of, or changes to a [Feature spec](testing_guide/testing_levels.md#frontend-feature-tests) | [Quality maintainer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_maintainers_qa) or [Quality reviewer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_reviewers_qa). |
| A new service to GitLab (Puma, Sidekiq, Gitaly are examples) | [Product manager](https://about.gitlab.com/company/team/). See the [process for adding a service component to GitLab](adding_service_component.md) for details. |
| Changes related to authentication or authorization | [Manage:Authentication and Authorization team member](https://about.gitlab.com/company/team/). Check the [code review section on the group page](https://about.gitlab.com/handbook/engineering/development/dev/manage/authentication-and-authorization/#additional-considerations) for more details. Patterns for files known to require review from the team are listed in the in the `Authentication and Authorization` section of the [`CODEOWNERS`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/CODEOWNERS) file, and the team will be listed in the approvers section of all merge requests that modify these files. |
diff --git a/doc/development/database_review.md b/doc/development/database_review.md
index 0e34e550098..76e9add215b 100644
--- a/doc/development/database_review.md
+++ b/doc/development/database_review.md
@@ -27,7 +27,7 @@ A database review is required for:
database review.
- Changes in Service Data metrics that use `count`, `distinct_count`, `estimate_batch_distinct_count` and `sum`.
These metrics could have complex queries over large tables.
- See the [Product Intelligence Guide](https://about.gitlab.com/handbook/product/product-intelligence-guide/)
+ See the [Analytics Instrumentation Guide](https://about.gitlab.com/handbook/product/analytics-instrumentation-guide/)
for implementation details.
A database reviewer is expected to look out for overly complex
diff --git a/doc/development/documentation/topic_types/index.md b/doc/development/documentation/topic_types/index.md
index 37ed876fc59..381f70914c6 100644
--- a/doc/development/documentation/topic_types/index.md
+++ b/doc/development/documentation/topic_types/index.md
@@ -23,7 +23,7 @@ The acronym refers to the first letter of each topic type.
In addition to the four primary topic types, you can use the following:
-- Page types: [Tutorials](tutorial.md) and [Get started](#get-started)
+- Page type: [Tutorials](tutorial.md)
- Topic type: [Related topics](#related-topics)
- Page or topic type: [Glossaries](glossary.md)
@@ -36,6 +36,7 @@ You should avoid:
- Topics that have one or two sentences only. In these cases:
- Incorporate the information in another topic.
- If the sentence links to another page, use a [Related topics](#related-topics) link instead.
+- Get started topics. To document a procedure for a single feature, use a [task](task.md). For a set of steps, use a [tutorial](tutorial.md).
## Topic title guidelines
@@ -63,27 +64,3 @@ full sentences, and so should not end in a period.
- [CI/CD variables](link-to-topic)
- [Environment variables](link-to-topic)
```
-
-## Get started
-
-A get started page is a set of steps to help a user get set up
-quickly to use a single GitLab feature or tool.
-It consists of more than one task.
-
-Get started pages should be in this format:
-
-```markdown
-# Title ("Get started with