summaryrefslogtreecommitdiff
path: root/app/services
diff options
context:
space:
mode:
Diffstat (limited to 'app/services')
-rw-r--r--app/services/projects/alerting/notify_service.rb49
-rw-r--r--app/services/projects/container_repository/delete_tags_service.rb24
-rw-r--r--app/services/projects/lsif_data_service.rb46
3 files changed, 109 insertions, 10 deletions
diff --git a/app/services/projects/alerting/notify_service.rb b/app/services/projects/alerting/notify_service.rb
new file mode 100644
index 00000000000..4ca3b154e4b
--- /dev/null
+++ b/app/services/projects/alerting/notify_service.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module Projects
+ module Alerting
+ class NotifyService < BaseService
+ include Gitlab::Utils::StrongMemoize
+
+ def execute(token)
+ return forbidden unless alerts_service_activated?
+ return unauthorized unless valid_token?(token)
+
+ process_incident_issues
+
+ ServiceResponse.success
+ rescue Gitlab::Alerting::NotificationPayloadParser::BadPayloadError
+ bad_request
+ end
+
+ private
+
+ delegate :alerts_service, :alerts_service_activated?, to: :project
+
+ def process_incident_issues
+ IncidentManagement::ProcessAlertWorker
+ .perform_async(project.id, parsed_payload)
+ end
+
+ def parsed_payload
+ Gitlab::Alerting::NotificationPayloadParser.call(params.to_h)
+ end
+
+ def valid_token?(token)
+ token == alerts_service.token
+ end
+
+ def bad_request
+ ServiceResponse.error(message: 'Bad Request', http_status: 400)
+ end
+
+ def unauthorized
+ ServiceResponse.error(message: 'Unauthorized', http_status: 401)
+ end
+
+ def forbidden
+ ServiceResponse.error(message: 'Forbidden', http_status: 403)
+ end
+ end
+ end
+end
diff --git a/app/services/projects/container_repository/delete_tags_service.rb b/app/services/projects/container_repository/delete_tags_service.rb
index 88ff3c2c9df..d19f275e928 100644
--- a/app/services/projects/container_repository/delete_tags_service.rb
+++ b/app/services/projects/container_repository/delete_tags_service.rb
@@ -14,12 +14,25 @@ module Projects
private
+ # Delete tags by name with a single DELETE request. This is only supported
+ # by the GitLab Container Registry fork. See
+ # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23325 for details.
+ def fast_delete(container_repository, tag_names)
+ deleted_tags = tag_names.select do |name|
+ container_repository.delete_tag_by_name(name)
+ end
+
+ deleted_tags.any? ? success(deleted: deleted_tags) : error('could not delete tags')
+ end
+
# Replace a tag on the registry with a dummy tag.
# This is a hack as the registry doesn't support deleting individual
# tags. This code effectively pushes a dummy image and assigns the tag to it.
# This way when the tag is deleted only the dummy image is affected.
+ # This is used to preverse compatibility with third-party registries that
+ # don't support fast delete.
# See https://gitlab.com/gitlab-org/gitlab/issues/15737 for a discussion
- def smart_delete(container_repository, tag_names)
+ def slow_delete(container_repository, tag_names)
# generates the blobs for the dummy image
dummy_manifest = container_repository.client.generate_empty_manifest(container_repository.path)
return error('could not generate manifest') if dummy_manifest.nil?
@@ -36,6 +49,15 @@ module Projects
end
end
+ def smart_delete(container_repository, tag_names)
+ fast_delete_enabled = Feature.enabled?(:container_registry_fast_tag_delete, default_enabled: true)
+ if fast_delete_enabled && container_repository.client.supports_tag_delete?
+ fast_delete(container_repository, tag_names)
+ else
+ slow_delete(container_repository, tag_names)
+ end
+ end
+
# update the manifests of the tags with the new dummy image
def replace_tag_manifests(container_repository, dummy_manifest, tag_names)
deleted_tags = {}
diff --git a/app/services/projects/lsif_data_service.rb b/app/services/projects/lsif_data_service.rb
index 00103f364bf..1282a0736e7 100644
--- a/app/services/projects/lsif_data_service.rb
+++ b/app/services/projects/lsif_data_service.rb
@@ -2,7 +2,8 @@
module Projects
class LsifDataService
- attr_reader :file, :project, :path, :commit_id
+ attr_reader :file, :project, :path, :commit_id,
+ :docs, :doc_ranges, :ranges, :def_refs
CACHE_EXPIRE_IN = 1.hour
@@ -14,19 +15,18 @@ module Projects
end
def execute
- docs, doc_ranges, ranges =
- fetch_data.values_at('docs', 'doc_ranges', 'ranges')
-
- doc_id = doc_id_from(docs)
+ fetch_data!
doc_ranges[doc_id]&.map do |range_id|
- line_data, column_data = ranges[range_id]['loc']
+ location, ref_id = ranges[range_id].values_at('loc', 'ref_id')
+ line_data, column_data = location
{
start_line: line_data.first,
end_line: line_data.last,
start_char: column_data.first,
- end_char: column_data.last
+ end_char: column_data.last,
+ definition_url: definition_url_for(def_refs[ref_id])
}
end
end
@@ -47,8 +47,17 @@ module Projects
end
end
- def doc_id_from(docs)
- docs.reduce(nil) do |doc_id, (id, doc_path)|
+ def fetch_data!
+ data = fetch_data
+
+ @docs = data['docs']
+ @doc_ranges = data['doc_ranges']
+ @ranges = data['ranges']
+ @def_refs = data['def_refs']
+ end
+
+ def doc_id
+ @doc_id ||= docs.reduce(nil) do |doc_id, (id, doc_path)|
next doc_id unless doc_path =~ /#{path}$/
if doc_id.nil? || docs[doc_id].size > doc_path.size
@@ -58,5 +67,24 @@ module Projects
doc_id
end
end
+
+ def dir_absolute_path
+ @dir_absolute_path ||= docs[doc_id]&.delete_suffix(path)
+ end
+
+ def definition_url_for(ref_id)
+ return unless range = ranges[ref_id]
+
+ def_doc_id, location = range.values_at('doc_id', 'loc')
+ localized_doc_url = docs[def_doc_id].delete_prefix(dir_absolute_path)
+
+ # location is stored as [[start_line, end_line], [start_char, end_char]]
+ start_line = location.first.first
+
+ line_anchor = "L#{start_line + 1}"
+ definition_ref_path = [commit_id, localized_doc_url].join('/')
+
+ Gitlab::Routing.url_helpers.project_blob_path(project, definition_ref_path, anchor: line_anchor)
+ end
end
end