Read about our upcoming Code of Conduct on this issue

Commit 66cddc08 authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent ec3d30b54172
This diff is collapsed.
......@@ -10,6 +10,7 @@ import {
GlLoadingIcon,
} from '@gitlab/ui';
import { s__, __, sprintf } from '~/locale';
import Tracking from '~/tracking';
import {
NAME_REGEX_LENGTH,
UPDATE_SETTINGS_ERROR_MESSAGE,
......@@ -27,10 +28,18 @@ export default {
GlCard,
GlLoadingIcon,
},
mixins: [Tracking.mixin()],
labelsConfig: {
cols: 3,
align: 'right',
},
data() {
return {
tracking: {
label: 'docker_container_retention_and_expiration_policies',
},
};
},
computed: {
...mapState(['formOptions', 'isLoading']),
...mapComputed(
......@@ -86,7 +95,12 @@ export default {
},
methods: {
...mapActions(['resetSettings', 'saveSettings']),
reset() {
this.track('reset_form');
this.resetSettings();
},
submit() {
this.track('submit_form');
this.saveSettings()
.then(() => this.$toast.show(UPDATE_SETTINGS_SUCCESS_MESSAGE, { type: 'success' }))
.catch(() => this.$toast.show(UPDATE_SETTINGS_ERROR_MESSAGE, { type: 'error' }));
......@@ -96,7 +110,7 @@ export default {
</script>
<template>
<form ref="form-element" @submit.prevent="submit" @reset.prevent="resetSettings">
<form ref="form-element" @submit.prevent="submit" @reset.prevent="reset">
<gl-card>
<template #header>
{{ s__('ContainerRegistry|Tag expiration policy') }}
......
......@@ -3,7 +3,13 @@
class Admin::ApplicationSettingsController < Admin::ApplicationController
include InternalRedirect
# NOTE: Use @application_setting in this controller when you need to access
# application_settings after it has been modified. This is because the
# ApplicationSetting model uses Gitlab::ThreadMemoryCache for caching and the
# cache might be stale immediately after an update.
# https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30233
before_action :set_application_setting
before_action :whitelist_query_limiting, only: [:usage_data]
before_action :validate_self_monitoring_feature_flag_enabled, only: [
:create_self_monitoring_project,
......@@ -79,6 +85,7 @@ def lets_encrypt_terms_of_service
redirect_to ::Gitlab::LetsEncrypt.terms_of_service_url
end
# Specs are in spec/requests/self_monitoring_project_spec.rb
def create_self_monitoring_project
job_id = SelfMonitoringProjectCreateWorker.perform_async
......@@ -88,6 +95,7 @@ def create_self_monitoring_project
}
end
# Specs are in spec/requests/self_monitoring_project_spec.rb
def status_create_self_monitoring_project
job_id = params[:job_id].to_s
......@@ -98,10 +106,7 @@ def status_create_self_monitoring_project
}
end
if Gitlab::CurrentSettings.self_monitoring_project_id.present?
return render status: :ok, json: self_monitoring_data
elsif SelfMonitoringProjectCreateWorker.in_progress?(job_id)
if SelfMonitoringProjectCreateWorker.in_progress?(job_id)
::Gitlab::PollingInterval.set_header(response, interval: 3_000)
return render status: :accepted, json: {
......@@ -109,12 +114,17 @@ def status_create_self_monitoring_project
}
end
if @application_setting.self_monitoring_project_id.present?
return render status: :ok, json: self_monitoring_data
end
render status: :bad_request, json: {
message: _('Self-monitoring project does not exist. Please check logs ' \
'for any error messages')
}
end
# Specs are in spec/requests/self_monitoring_project_spec.rb
def delete_self_monitoring_project
job_id = SelfMonitoringProjectDeleteWorker.perform_async
......@@ -124,6 +134,7 @@ def delete_self_monitoring_project
}
end
# Specs are in spec/requests/self_monitoring_project_spec.rb
def status_delete_self_monitoring_project
job_id = params[:job_id].to_s
......@@ -134,12 +145,7 @@ def status_delete_self_monitoring_project
}
end
if Gitlab::CurrentSettings.self_monitoring_project_id.nil?
return render status: :ok, json: {
message: _('Self-monitoring project has been successfully deleted')
}
elsif SelfMonitoringProjectDeleteWorker.in_progress?(job_id)
if SelfMonitoringProjectDeleteWorker.in_progress?(job_id)
::Gitlab::PollingInterval.set_header(response, interval: 3_000)
return render status: :accepted, json: {
......@@ -147,6 +153,12 @@ def status_delete_self_monitoring_project
}
end
if @application_setting.self_monitoring_project_id.nil?
return render status: :ok, json: {
message: _('Self-monitoring project has been successfully deleted')
}
end
render status: :bad_request, json: {
message: _('Self-monitoring project was not deleted. Please check logs ' \
'for any error messages')
......@@ -161,8 +173,8 @@ def validate_self_monitoring_feature_flag_enabled
def self_monitoring_data
{
project_id: Gitlab::CurrentSettings.self_monitoring_project_id,
project_full_path: Gitlab::CurrentSettings.self_monitoring_project&.full_path
project_id: @application_setting.self_monitoring_project_id,
project_full_path: @application_setting.self_monitoring_project&.full_path
}
end
......
......@@ -24,7 +24,7 @@ def destroy
def mark_as_ham
spam_log = SpamLog.find(params[:id])
if HamService.new(spam_log).mark_as_ham!
if Spam::HamService.new(spam_log).mark_as_ham!
redirect_to admin_spam_logs_path, notice: _('Spam log successfully submitted as ham.')
else
redirect_to admin_spam_logs_path, alert: _('Error with Akismet. Please check the logs for more info.')
......
......@@ -8,7 +8,6 @@ class SentryDetailedErrorResolver < BaseResolver
description: 'ID of the Sentry issue'
def resolve(**args)
project = object
current_user = context[:current_user]
issue_id = GlobalID.parse(args[:id]).model_id
......@@ -23,6 +22,14 @@ def resolve(**args)
issue
end
private
def project
return object.gitlab_project if object.respond_to?(:gitlab_project)
object
end
end
end
end
# frozen_string_literal: true
module Resolvers
module ErrorTracking
class SentryErrorCollectionResolver < BaseResolver
def resolve(**args)
project = object
service = ::ErrorTracking::ListIssuesService.new(
project,
context[:current_user]
)
Gitlab::ErrorTracking::ErrorCollection.new(
external_url: service.external_url,
project: project
)
end
end
end
end
# frozen_string_literal: true
module Resolvers
module ErrorTracking
class SentryErrorsResolver < BaseResolver
def resolve(**args)
args[:cursor] = args.delete(:after)
project = object.project
result = ::ErrorTracking::ListIssuesService.new(
project,
context[:current_user],
args
).execute
next_cursor = result[:pagination]&.dig('next', 'cursor')
previous_cursor = result[:pagination]&.dig('previous', 'cursor')
issues = result[:issues]
# ReactiveCache is still fetching data
return if issues.nil?
Gitlab::Graphql::ExternallyPaginatedArray.new(previous_cursor, next_cursor, *issues)
end
end
end
end
......@@ -4,8 +4,9 @@ module Types
module ErrorTracking
class SentryDetailedErrorType < ::Types::BaseObject
graphql_name 'SentryDetailedError'
description 'A Sentry error.'
present_using SentryDetailedErrorPresenter
present_using SentryErrorPresenter
authorize :read_sentry_issue
......@@ -92,18 +93,6 @@ class SentryDetailedErrorType < ::Types::BaseObject
field :tags, Types::ErrorTracking::SentryErrorTagsType,
null: false,
description: 'Tags associated with the Sentry Error'
def first_seen
DateTime.parse(object.first_seen)
end
def last_seen
DateTime.parse(object.last_seen)
end
def project_id
Gitlab::GlobalId.build(model_name: 'Project', id: object.project_id).to_s
end
end
end
end
# frozen_string_literal: true
module Types
module ErrorTracking
class SentryErrorCollectionType < ::Types::BaseObject
graphql_name 'SentryErrorCollection'
description 'An object containing a collection of Sentry errors, and a detailed error.'
authorize :read_sentry_issue
field :errors,
Types::ErrorTracking::SentryErrorType.connection_type,
connection: false,
null: true,
description: "Collection of Sentry Errors",
extensions: [Gitlab::Graphql::Extensions::ExternallyPaginatedArrayExtension],
resolver: Resolvers::ErrorTracking::SentryErrorsResolver do
argument :search_term,
String,
description: 'Search term for the Sentry error.',
required: false
argument :sort,
String,
description: 'Attribute to sort on. Options are frequency, first_seen, last_seen. last_seen is default.',
required: false
end
field :detailed_error, Types::ErrorTracking::SentryDetailedErrorType,
null: true,
description: 'Detailed version of a Sentry error on the project',
resolver: Resolvers::ErrorTracking::SentryDetailedErrorResolver
field :external_url,
GraphQL::STRING_TYPE,
null: true,
description: "External URL for Sentry"
end
end
end
# frozen_string_literal: true
module Types
module ErrorTracking
# rubocop: disable Graphql/AuthorizeTypes
class SentryErrorType < ::Types::BaseObject
graphql_name 'SentryError'
description 'A Sentry error. A simplified version of SentryDetailedError.'
present_using SentryErrorPresenter
field :id, GraphQL::ID_TYPE,
null: false,
description: 'ID (global ID) of the error'
field :sentry_id, GraphQL::STRING_TYPE,
method: :id,
null: false,
description: 'ID (Sentry ID) of the error'
field :first_seen, Types::TimeType,
null: false,
description: 'Timestamp when the error was first seen'
field :last_seen, Types::TimeType,
null: false,
description: 'Timestamp when the error was last seen'
field :title, GraphQL::STRING_TYPE,
null: false,
description: 'Title of the error'
field :type, GraphQL::STRING_TYPE,
null: false,
description: 'Type of the error'
field :user_count, GraphQL::INT_TYPE,
null: false,
description: 'Count of users affected by the error'
field :count, GraphQL::INT_TYPE,
null: false,
description: 'Count of occurrences'
field :message, GraphQL::STRING_TYPE,
null: true,
description: 'Sentry metadata message of the error'
field :culprit, GraphQL::STRING_TYPE,
null: false,
description: 'Culprit of the error'
field :external_url, GraphQL::STRING_TYPE,
null: false,
description: 'External URL of the error'
field :short_id, GraphQL::STRING_TYPE,
null: false,
description: 'Short ID (Sentry ID) of the error'
field :status, Types::ErrorTracking::SentryErrorStatusEnum,
null: false,
description: 'Status of the error'
field :frequency, [Types::ErrorTracking::SentryErrorFrequencyType],
null: false,
description: 'Last 24hr stats of the error'
field :sentry_project_id, GraphQL::ID_TYPE,
method: :project_id,
null: false,
description: 'ID of the project (Sentry project)'
field :sentry_project_name, GraphQL::STRING_TYPE,
method: :project_name,
null: false,
description: 'Name of the project affected by the error'
field :sentry_project_slug, GraphQL::STRING_TYPE,
method: :project_slug,
null: false,
description: 'Slug of the project affected by the error'
end
# rubocop: enable Graphql/AuthorizeTypes
end
end
......@@ -173,6 +173,12 @@ class ProjectType < BaseObject
null: true,
description: 'Snippets of the project',
resolver: Resolvers::Projects::SnippetsResolver
field :sentry_errors,
Types::ErrorTracking::SentryErrorCollectionType,
null: true,
description: 'Paginated collection of Sentry errors on the project',
resolver: Resolvers::ErrorTracking::SentryErrorCollectionResolver
end
end
......
......@@ -484,10 +484,10 @@ def expire_note_etag_cache_for_related_mrs
end
def commit_reference(from, referable_commit_id, full: false)
reference = project.to_reference(from, full: full)
base = project.to_reference_base(from, full: full)
if reference.present?
"#{reference}#{self.class.reference_prefix}#{referable_commit_id}"
if base.present?
"#{base}#{self.class.reference_prefix}#{referable_commit_id}"
else
referable_commit_id
end
......
......@@ -92,7 +92,7 @@ def to_s
alias_method :id, :to_s
def to_reference(from = nil, full: false)
project_reference = project.to_reference(from, full: full)
project_reference = project.to_reference_base(from, full: full)
if project_reference.present?
project_reference + self.class.reference_prefix + self.id
......@@ -102,7 +102,7 @@ def to_reference(from = nil, full: false)
end
def reference_link_text(from = nil)
project_reference = project.to_reference(from)
project_reference = project.to_reference_base(from)
reference = ref_from + notation + ref_to
if project_reference.present?
......
......@@ -23,6 +23,14 @@ def to_reference(_from = nil, full:)
''
end
# If this referable object can serve as the base for the
# reference of child objects (e.g. projects are the base of
# issues), but it is formatted differently, then you may wish
# to override this method.
def to_reference_base(from = nil, full:)
to_reference(from, full: full)
end
def reference_link_text(from = nil)
to_reference(from)
end
......
......@@ -173,7 +173,7 @@ def hook_attrs
def to_reference(from = nil, full: false)
reference = "#{self.class.reference_prefix}#{iid}"
"#{project.to_reference(from, full: full)}#{reference}"
"#{project.to_reference_base(from, full: full)}#{reference}"
end
def suggested_branch_name
......
......@@ -225,7 +225,7 @@ def to_reference(from = nil, target_project: nil, format: :id, full: false)
reference = "#{self.class.reference_prefix}#{format_reference}"
if from
"#{from.to_reference(target_project, full: full)}#{reference}"
"#{from.to_reference_base(target_project, full: full)}#{reference}"
else
reference
end
......
......@@ -396,7 +396,7 @@ def hook_attrs
def to_reference(from = nil, full: false)
reference = "#{self.class.reference_prefix}#{iid}"
"#{project.to_reference(from, full: full)}#{reference}"
"#{project.to_reference_base(from, full: full)}#{reference}"
end
def commits(limit: nil)
......
......@@ -228,7 +228,7 @@ def to_reference(from = nil, format: :name, full: false)
reference = "#{self.class.reference_prefix}#{format_reference}"
if project
"#{project.to_reference(from, full: full)}#{reference}"
"#{project.to_reference_base(from, full: full)}#{reference}"
else
reference
end
......
......@@ -1068,12 +1068,19 @@ def to_param
end
end
def to_reference_with_postfix
"#{to_reference(full: true)}#{self.class.reference_postfix}"
# Produce a valid reference (see Referable#to_reference)
#
# NB: For projects, all references are 'full' - i.e. they all include the
# full_path, rather than just the project name. For this reason, we ignore
# the value of `full:` passed to this method, which is part of the Referable
# interface.
def to_reference(from = nil, full: false)
base = to_reference_base(from, full: true)
"#{base}#{self.class.reference_postfix}"
end
# `from` argument can be a Namespace or Project.
def to_reference(from = nil, full: false)
def to_reference_base(from = nil, full: false)
if full || cross_namespace_reference?(from)
full_path
elsif cross_project_reference?(from)
......
......@@ -180,7 +180,7 @@ def to_reference(from = nil, full: false)
reference = "#{self.class.reference_prefix}#{id}"
if project.present?
"#{project.to_reference(from, full: full)}#{reference}"
"#{project.to_reference_base(from, full: full)}#{reference}"
else
reference
end
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment