1# frozen_string_literal: true 2 3module Gitlab 4 module Tracking 5 InvalidEventError = Class.new(RuntimeError) 6 7 class EventDefinition 8 EVENT_SCHEMA_PATH = Rails.root.join('config', 'events', 'schema.json') 9 BASE_REPO_PATH = 'https://gitlab.com/gitlab-org/gitlab/-/blob/master' 10 SCHEMA = ::JSONSchemer.schema(Pathname.new(EVENT_SCHEMA_PATH)) 11 12 attr_reader :path 13 attr_reader :attributes 14 15 class << self 16 def paths 17 @paths ||= [Rails.root.join('config', 'events', '*.yml'), Rails.root.join('ee', 'config', 'events', '*.yml')] 18 end 19 20 def definitions 21 paths.each_with_object({}) do |glob_path, definitions| 22 load_all_from_path!(definitions, glob_path) 23 end 24 end 25 26 private 27 28 def load_from_file(path) 29 definition = File.read(path) 30 definition = YAML.safe_load(definition) 31 definition.deep_symbolize_keys! 32 33 self.new(path, definition).tap(&:validate!) 34 rescue StandardError => e 35 Gitlab::ErrorTracking.track_and_raise_for_dev_exception(Gitlab::Tracking::InvalidEventError.new(e.message)) 36 end 37 38 def load_all_from_path!(definitions, glob_path) 39 Dir.glob(glob_path).each do |path| 40 definition = load_from_file(path) 41 definitions[definition.path] = definition 42 end 43 end 44 end 45 46 def initialize(path, opts = {}) 47 @path = path 48 @attributes = opts 49 end 50 51 def to_h 52 attributes 53 end 54 alias_method :to_dictionary, :to_h 55 56 def yaml_path 57 path.delete_prefix(Rails.root.to_s) 58 end 59 60 def validate! 61 SCHEMA.validate(attributes.stringify_keys).each do |error| 62 error_message = <<~ERROR_MSG 63 Error type: #{error['type']} 64 Data: #{error['data']} 65 Path: #{error['data_pointer']} 66 Details: #{error['details']} 67 Definition file: #{path} 68 ERROR_MSG 69 70 Gitlab::ErrorTracking.track_and_raise_for_dev_exception(Gitlab::Tracking::InvalidEventError.new(error_message)) 71 end 72 end 73 74 private 75 76 def method_missing(method, *args) 77 attributes[method] || super 78 end 79 end 80 end 81end 82