peak_flow_utils 0.1.14 → 0.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7e3d80778a6e2f090ed1247e8afd8b0cf95c1c57d96a01315534f32aa0a56d00
4
- data.tar.gz: b4ab6fd0ba591e3f750dca4d1fea08de84d2d04a150b0bf6a8a90c15928b4157
3
+ metadata.gz: b4fb7a276f751a58ba19b74e73955323e0f1b89215312b50ee3e3b9cf89a85f4
4
+ data.tar.gz: 29edd9b2f4225cf2ea74c67d4fccd1b21a0149781f2cacc168309ef8dd3082c6
5
5
  SHA512:
6
- metadata.gz: 9dc474ec28b8221fb5730bad562121ef0925e6bb2cd0f554e759d51a5daba2169bb0290253b10dfda1a140a616c21751f228c2994bcddf468c6a5bae3b7d741a
7
- data.tar.gz: 57b9245ce4892aa877dd01b7947f9db2a19a80cb1355a2a6ab57350779cd3c9090567417bd369399d8a4daba65c00d867c76fdb506b85e5342a330c3e79414bd
6
+ metadata.gz: 18328934879ae9fbb148e812926d68b5dca82837f929e5c3f3228bc4bc34bb140e8d42013333ef68976931819960d45110b26a8bf8bb2b37e363b8a519bf0ee9
7
+ data.tar.gz: 4251f1f1213fc0e9dfa426c7c4a1e75c53dbd23dff37ce09213f857ff7b7fba56251875d17a7baed74273d744f29b03bd9fa3e41f7a877319ada3cf9760bf9b4
@@ -0,0 +1,45 @@
1
+ class PeakFlowUtils::DeepMerger < PeakFlowUtils::ApplicationService
2
+ def initialize(hashes:)
3
+ @hashes = hashes
4
+ end
5
+
6
+ def perform
7
+ merged = {}
8
+
9
+ @hashes.each do |hash|
10
+ merge_hash(hash, merged)
11
+ end
12
+
13
+ succeed! merged
14
+ end
15
+
16
+ def merge_something(object, merged)
17
+ if object.is_a?(Array)
18
+ merge_array(object, merged)
19
+ elsif object.is_a?(Hash)
20
+ merge_hash(object, merged)
21
+ else
22
+ raise "Unknown object: #{object.class.name}"
23
+ end
24
+ end
25
+
26
+ def merge_array(array, merged)
27
+ array.each do |value|
28
+ merged << value
29
+ end
30
+ end
31
+
32
+ def merge_hash(hash, merged)
33
+ hash.each do |key, value|
34
+ if !merged.key?(key)
35
+ merged[key] = value
36
+ elsif value.is_a?(Array)
37
+ merge_array(value, merged[key])
38
+ elsif value.is_a?(Hash)
39
+ merge_hash(value, merged[key])
40
+ else
41
+ raise "Unknown object: #{object.class.name}"
42
+ end
43
+ end
44
+ end
45
+ end
@@ -14,8 +14,41 @@ class PeakFlowUtils::Notifier
14
14
  @current
15
15
  end
16
16
 
17
- def self.notify(*args)
18
- PeakFlowUtils::Notifier.current.notify(*args)
17
+ def self.current_parameters(parameters: nil)
18
+ hashes = PeakFlowUtils::Notifier.current_parameters_hashes
19
+ hashes << parameters if parameters
20
+
21
+ PeakFlowUtils::DeepMerger.execute!(hashes: hashes)
22
+ end
23
+
24
+ def self.current_parameters_hashes
25
+ hashes = []
26
+
27
+ Thread.current[:peakflow_utils] ||= {}
28
+ Thread.current[:peakflow_utils].dig(:notifier, :with_parameters)&.each_value do |more_parameters|
29
+ hashes << more_parameters
30
+ end
31
+
32
+ hashes
33
+ end
34
+
35
+ def self.notify(*args, **opts, &blk)
36
+ PeakFlowUtils::Notifier.current.notify(*args, **opts, &blk)
37
+ end
38
+
39
+ def self.with_parameters(parameters)
40
+ random_id = SecureRandom.hex(16)
41
+
42
+ Thread.current[:peakflow_utils] ||= {}
43
+ Thread.current[:peakflow_utils][:notifier] ||= {}
44
+ Thread.current[:peakflow_utils][:notifier][:with_parameters] ||= {}
45
+ Thread.current[:peakflow_utils][:notifier][:with_parameters][random_id] = parameters
46
+
47
+ begin
48
+ yield
49
+ ensure
50
+ Thread.current[:peakflow_utils][:notifier][:with_parameters].delete(random_id)
51
+ end
19
52
  end
20
53
 
21
54
  def initialize(auth_token:)
@@ -29,6 +62,8 @@ class PeakFlowUtils::Notifier
29
62
  error: error
30
63
  )
31
64
 
65
+ merged_parameters = PeakFlowUtils::Notifier.current_parameters(parameters: parameters)
66
+
32
67
  uri = URI("https://www.peakflow.io/errors/reports")
33
68
 
34
69
  https = Net::HTTP.new(uri.host, uri.port)
@@ -43,7 +78,7 @@ class PeakFlowUtils::Notifier
43
78
  file_path: error_parser.file_path,
44
79
  line_number: error_parser.line_number,
45
80
  message: error.message,
46
- parameters: parameters,
81
+ parameters: merged_parameters,
47
82
  remote_ip: error_parser.remote_ip,
48
83
  url: error_parser.url,
49
84
  user_agent: error_parser.user_agent
@@ -9,13 +9,13 @@ class PeakFlowUtils::NotifierRack
9
9
  rescue Exception => e # rubocop:disable Lint/RescueException
10
10
  controller = env["action_controller.instance"]
11
11
  request = controller&.request
12
- parameters = {}.merge(request.GET).merge(request.POST)
13
12
 
14
- PeakFlowUtils::Notifier.notify(
15
- environment: env,
16
- error: e,
17
- parameters: parameters
18
- )
13
+ PeakFlowUtils::Notifier.with_parameters(rack: {get: request.GET, post: request.POST}) do
14
+ PeakFlowUtils::Notifier.notify(
15
+ environment: env,
16
+ error: e
17
+ )
18
+ end
19
19
 
20
20
  raise e
21
21
  end
@@ -1,3 +1,3 @@
1
1
  module PeakFlowUtils
2
- VERSION = "0.1.14".freeze
2
+ VERSION = "0.1.15".freeze
3
3
  end
@@ -13,7 +13,6 @@ module PeakFlowUtils
13
13
  autoload :NotifierRails, "#{path}/notifier_rails"
14
14
  autoload :NotifierResponse, "#{path}/notifier_response"
15
15
  autoload :NotifierSidekiq, "#{path}/notifier_sidekiq"
16
- autoload :RspecHelper, "#{path}/rspec_helper"
17
16
  autoload :HandlerHelper, "#{path}/handler_helper"
18
17
 
19
18
  autoload :ApplicationRecord, "#{models_path}/application_record"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: peak_flow_utils
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.14
4
+ version: 0.1.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - kaspernj
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-10-04 00:00:00.000000000 Z
11
+ date: 2022-02-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: 1.0.0
61
+ version: 1.0.5
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: 1.0.0
68
+ version: 1.0.5
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: redis
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -111,8 +111,7 @@ dependencies:
111
111
  description: Utilities to be used with PeakFlow.
112
112
  email:
113
113
  - kaspernj@gmail.com
114
- executables:
115
- - peak_flow_rspec_files
114
+ executables: []
116
115
  extensions: []
117
116
  extra_rdoc_files: []
118
117
  files:
@@ -135,6 +134,7 @@ files:
135
134
  - app/services/peak_flow_utils/attribute_service.rb
136
135
  - app/services/peak_flow_utils/configuration_service.rb
137
136
  - app/services/peak_flow_utils/database_initializer_service.rb
137
+ - app/services/peak_flow_utils/deep_merger.rb
138
138
  - app/services/peak_flow_utils/erb_inspector.rb
139
139
  - app/services/peak_flow_utils/erb_inspector/file_inspector.rb
140
140
  - app/services/peak_flow_utils/erb_inspector/translation_inspector.rb
@@ -143,7 +143,6 @@ files:
143
143
  - app/services/peak_flow_utils/model_inspector.rb
144
144
  - app/services/peak_flow_utils/translation_service.rb
145
145
  - app/services/peak_flow_utils/translations_parser_service.rb
146
- - bin/peak_flow_rspec_files
147
146
  - config/routes.rb
148
147
  - lib/peak_flow_utils.rb
149
148
  - lib/peak_flow_utils/engine.rb
@@ -167,7 +166,6 @@ files:
167
166
  - lib/peak_flow_utils/notifier_rails.rb
168
167
  - lib/peak_flow_utils/notifier_response.rb
169
168
  - lib/peak_flow_utils/notifier_sidekiq.rb
170
- - lib/peak_flow_utils/rspec_helper.rb
171
169
  - lib/peak_flow_utils/version.rb
172
170
  - lib/tasks/peak_flow_utils_tasks.rake
173
171
  homepage: https://github.com/kaspernj/peak_flow_utils
@@ -189,7 +187,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
189
187
  - !ruby/object:Gem::Version
190
188
  version: '0'
191
189
  requirements: []
192
- rubygems_version: 3.1.6
190
+ rubygems_version: 3.2.32
193
191
  signing_key:
194
192
  specification_version: 4
195
193
  summary: Utilities to be used with PeakFlow.
@@ -1,21 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- # This task detects and prints out the RSpec files for the current build group
4
-
5
- require "#{__dir__}/../lib/peak_flow_utils"
6
-
7
- args = {}
8
- ARGV.each do |arg|
9
- if (match = arg.match(/\A--(.+?)=(.+)\Z/))
10
- args[match[1]] = match[2]
11
- end
12
- end
13
-
14
- rspec_helper = PeakFlowUtils::RspecHelper.new(
15
- groups: args.fetch("groups").to_i,
16
- group_number: args.fetch("group-number").to_i,
17
- only_types: args["only-types"]&.split(","),
18
- tags: args["tags"]&.split(",")
19
- )
20
-
21
- print rspec_helper.group_files.map { |group_file| group_file.fetch(:path) }.join(" ")
@@ -1,209 +0,0 @@
1
- class PeakFlowUtils::RspecHelper
2
- attr_reader :only_types, :tags
3
-
4
- def initialize(groups:, group_number:, only_types: nil, tags: nil)
5
- @groups = groups
6
- @group_number = group_number
7
- @example_data_exists = File.exist?("spec/examples.txt")
8
- @only_types = only_types
9
- @tags = tags
10
- end
11
-
12
- def example_data_exists?
13
- @example_data_exists
14
- end
15
-
16
- def example_data
17
- @example_data ||= begin
18
- raw_data = File.read("spec/examples.txt")
19
-
20
- result = []
21
- raw_data.scan(/^\.\/(.+)\[(.+?)\]\s+\|\s+(.+?)\s+\|\s+((.+?) seconds|)\s+\|$/) do |match|
22
- file_path = match[0]
23
- spec_result = match[1]
24
- seconds = match[4]&.to_f
25
-
26
- spec_data = {
27
- file_path: file_path,
28
- spec_result: spec_result,
29
- seconds: seconds
30
- }
31
-
32
- result << spec_data
33
- end
34
-
35
- result
36
- end
37
- end
38
-
39
- def example_files
40
- @example_files ||= begin
41
- files = {}
42
- example_data.each do |spec_data|
43
- file_path = spec_data.fetch(:file_path)
44
- seconds = spec_data.fetch(:seconds)
45
-
46
- files[file_path] ||= {examples: 0, seconds: 0.0}
47
- files[file_path][:examples] += 1
48
- files[file_path][:seconds] += seconds if seconds
49
- end
50
-
51
- files
52
- end
53
- end
54
-
55
- def example_file(path)
56
- example_files[path]
57
- end
58
-
59
- def group_files
60
- return @group_files if @group_files
61
-
62
- sorted_files.each do |file|
63
- file_path = file.fetch(:path)
64
- file_data = example_file(file_path) if example_data_exists?
65
-
66
- if file_data
67
- examples = file_data.fetch(:examples)
68
- seconds = file_data.fetch(:seconds)
69
- else
70
- examples = file.fetch(:examples)
71
- end
72
-
73
- group = group_with_least
74
- group[:examples] += examples
75
- group[:files] << file
76
- group[:seconds] += seconds if seconds
77
- end
78
-
79
- @group_files = group_orders[@group_number - 1].fetch(:files)
80
- end
81
-
82
- def group_orders
83
- @group_orders ||= begin
84
- group_orders = []
85
- @groups.times do
86
- group_orders << {
87
- examples: 0,
88
- files: [],
89
- seconds: 0.0
90
- }
91
- end
92
- group_orders
93
- end
94
- end
95
-
96
- def group_with_least
97
- group_orders.min do |group1, group2|
98
- if example_data_exists? && group1.fetch(:seconds) != 0.0 && group2.fetch(:seconds) != 0.0
99
- group1.fetch(:seconds) <=> group2.fetch(:seconds)
100
- else
101
- group1.fetch(:examples) <=> group2.fetch(:examples)
102
- end
103
- end
104
- end
105
-
106
- # Sort them so that they are sorted by file path in three groups so each group have an equal amount of controller specs, features specs and so on
107
- def sorted_files
108
- files.values.sort do |file1, file2|
109
- file1_path = file1.fetch(:path)
110
- file2_path = file2.fetch(:path)
111
-
112
- file1_data = example_file(file1_path) if example_data_exists?
113
- file2_data = example_file(file2_path) if example_data_exists?
114
-
115
- if file1_data && file2_data && file1_data.fetch(:seconds) != 0.0 && file2_data.fetch(:seconds) != 0.0
116
- value1 = file1_data[:seconds]
117
- else
118
- value1 = file1.fetch(:points)
119
- end
120
-
121
- if file2_data && file1_data && file2_data.fetch(:seconds) != 0.0 && file2_data.fetch(:seconds) != 0.0
122
- value2 = file2_data[:seconds]
123
- else
124
- value2 = file2.fetch(:points)
125
- end
126
-
127
- if value1 == value2
128
- value2 = file1_path
129
- value1 = file2_path
130
- end
131
-
132
- value2 <=> value1
133
- end
134
- end
135
-
136
- private
137
-
138
- def dry_result
139
- @dry_result ||= begin
140
- require "json"
141
- require "rspec/core"
142
-
143
- output_capture = StringIO.new
144
- RSpec::Core::Runner.run(rspec_options, $stderr, output_capture)
145
-
146
- result = ::JSON.parse(output_capture.string)
147
-
148
- raise "No examples were found" if result.fetch("examples").empty?
149
-
150
- result
151
- end
152
- end
153
-
154
- def dry_file(path)
155
- files.fetch(path)
156
- end
157
-
158
- def files
159
- @files ||= begin
160
- result = {}
161
- dry_result.fetch("examples").each do |example|
162
- file_path = example.fetch("file_path")
163
- file_path = file_path[2, file_path.length]
164
- type = type_from_path(file_path)
165
- points = points_from_type(type)
166
-
167
- next if ignore_type?(type)
168
-
169
- result[file_path] = {examples: 0, path: file_path, points: 0, type: type} unless result.key?(file_path)
170
- result[file_path][:examples] += 1
171
- result[file_path][:points] += points
172
- end
173
-
174
- result
175
- end
176
- end
177
-
178
- def ignore_type?(type)
179
- only_types && !only_types.include?(type) # rubocop:disable Rails/NegateInclude:, Style/SafeNavigation
180
- end
181
-
182
- def points_from_type(type)
183
- if type == "feature" || type == "system"
184
- 10
185
- elsif type == "controllers"
186
- 3
187
- else
188
- 1
189
- end
190
- end
191
-
192
- def rspec_options
193
- rspec_options = ["--dry-run", "--format", "json"]
194
-
195
- tags&.each do |tag|
196
- rspec_options += ["--tag", tag]
197
- end
198
-
199
- # Add the folder with all the specs, which is required when running programmatically
200
- rspec_options << "spec"
201
-
202
- rspec_options
203
- end
204
-
205
- def type_from_path(file_path)
206
- match = file_path.match(/^spec\/(.+?)\//)
207
- match[1] if match
208
- end
209
- end