fbe 0.0.31 → 0.0.33

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ef0c6fea054357e3c16f72388ee2e7ee078877da50724e05915498605903f59f
4
- data.tar.gz: c521b892672f55e9e8584f5d5bfb169ff032b483aa46c10cf55e1fcd245bf289
3
+ metadata.gz: 489236ecdcc30bb5a0753133c145fa827be2a246b1b3c211bce091a27d1849bf
4
+ data.tar.gz: d43995afcafd252f35012f16f92f1e25c8d91526e1b940ead820f62c2c7c8ef6
5
5
  SHA512:
6
- metadata.gz: aad179e03869dd93a4ad846e3d3a8cbcb0af1cec3b9ea9ed1d91688b2f854a73b7b4769e268c67aa2949c82e726abcc4518d486fde006edb6499e1614656b970
7
- data.tar.gz: 48efb2b4da4e2e4f870e8e0d6cb3acf29d879db619874039699cf7529dddad33bf24863bdebca67a175e6303c9cd8726e1ea640f2ce5140e14c0c32917e5775a
6
+ metadata.gz: 41f313679fb74d37f4eac6f19e680230f48a3a9e4db781a90de88f310653d95bd4ea9ab735e7dab47b48f7066687e324975e08764ead17a27bab16e4d164a59a
7
+ data.tar.gz: e663d0c6316264c3066308827d08177860f3957591d4aa72d1a2a0e8f94d0c1a4c6ca9e981451581c89dc87432d38aa3964ba38b06b7940ad98a041375e42665
data/Gemfile.lock CHANGED
@@ -258,6 +258,7 @@ PLATFORMS
258
258
  arm64-darwin-22
259
259
  x64-mingw-ucrt
260
260
  x86_64-darwin-20
261
+ x86_64-darwin-21
261
262
  x86_64-linux
262
263
 
263
264
  DEPENDENCIES
data/README.md CHANGED
@@ -1,7 +1,6 @@
1
1
  # FactBase Extended (FBE)
2
2
 
3
3
  [![DevOps By Rultor.com](http://www.rultor.com/b/zerocracy/fbe)](http://www.rultor.com/p/zerocracy/fbe)
4
- [![We recommend RubyMine](https://www.elegantobjects.org/rubymine.svg)](https://www.jetbrains.com/ruby/)
5
4
 
6
5
  [![rake](https://github.com/zerocracy/fbe/actions/workflows/rake.yml/badge.svg)](https://github.com/zerocracy/fbe/actions/workflows/rake.yml)
7
6
  [![PDD status](http://www.0pdd.com/svg?name=zerocracy/fbe)](http://www.0pdd.com/p?name=zerocracy/fbe)
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ # MIT License
4
+ #
5
+ # Copyright (c) 2024 Zerocracy
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ # of this software and associated documentation files (the "Software"), to deal
9
+ # in the Software without restriction, including without limitation the rights
10
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ # copies of the Software, and to permit persons to whom the Software is
12
+ # furnished to do so, subject to the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be included in all
15
+ # copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ # SOFTWARE.
24
+
25
+ require 'faraday'
26
+
27
+ # Faraday Middleware that monitors GitHub API rate limits.
28
+ class Fbe::Middleware::Quota < Faraday::Middleware
29
+ def initialize(app, logger: Loog::NULL, pause: 60, limit: 100, rate: 5)
30
+ super(app)
31
+ @limit = limit
32
+ @requests = 0
33
+ @app = app
34
+ @logger = logger
35
+ @pause = pause
36
+ @rate = rate
37
+ end
38
+
39
+ def call(env)
40
+ @requests += 1
41
+ response = @app.call(env)
42
+ if out_of_limit?(env)
43
+ @logger.info(
44
+ "Too much GitHub API quota consumed, pausing for #{@pause} seconds"
45
+ )
46
+ sleep(@pause)
47
+ @requests = 0
48
+ end
49
+ response
50
+ end
51
+
52
+ private
53
+
54
+ def out_of_limit?(env)
55
+ remaining = env.response_headers['x-ratelimit-remaining'].to_i
56
+ (@requests % @limit).zero? && remaining < @rate
57
+ end
58
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ # MIT License
4
+ #
5
+ # Copyright (c) 2024 Zerocracy
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ # of this software and associated documentation files (the "Software"), to deal
9
+ # in the Software without restriction, including without limitation the rights
10
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ # copies of the Software, and to permit persons to whom the Software is
12
+ # furnished to do so, subject to the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be included in all
15
+ # copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ # SOFTWARE.
24
+
25
+ # The module.
26
+ module Fbe::Middleware
27
+ # empty
28
+ end
data/lib/fbe/octo.rb CHANGED
@@ -30,6 +30,7 @@ require 'verbose'
30
30
  require 'faraday/http_cache'
31
31
  require 'faraday/retry'
32
32
  require_relative '../fbe'
33
+ require_relative 'middleware/quota'
33
34
 
34
35
  def Fbe.octo(options: $options, global: $global, loog: $loog)
35
36
  raise 'The $global is not set' if global.nil?
@@ -75,6 +76,11 @@ def Fbe.octo(options: $options, global: $global, loog: $loog)
75
76
  methods: [:get],
76
77
  backoff_factor: 2
77
78
  )
79
+ builder.use(
80
+ Fbe::Middleware::Quota,
81
+ logger: loog,
82
+ pause: options.github_api_pause
83
+ )
78
84
  builder.use(Faraday::HttpCache, serializer: Marshal, shared_cache: false, logger: Loog::NULL)
79
85
  builder.use(Octokit::Response::RaiseError)
80
86
  builder.use(Faraday::Response::Logger, Loog::NULL)
@@ -247,6 +253,26 @@ class Fbe::FakeOctokit
247
253
  ]
248
254
  end
249
255
 
256
+ def list_issues(repo, _options = {})
257
+ [
258
+ issue(repo, 42),
259
+ issue(repo, 43)
260
+ ]
261
+ end
262
+
263
+ def issue(repo, number)
264
+ {
265
+ id: 42,
266
+ number:,
267
+ repo: {
268
+ full_name: repo
269
+ },
270
+ pull_request: {
271
+ merged_at: nil
272
+ }
273
+ }
274
+ end
275
+
250
276
  def pull_request(repo, number)
251
277
  {
252
278
  id: 42,
@@ -289,6 +315,22 @@ class Fbe::FakeOctokit
289
315
  }
290
316
  end
291
317
 
318
+ def commits_since(repo, _since)
319
+ [
320
+ commit(repo, 'a1b2c3d4e5f6a1b2c3d4e5f6'),
321
+ commit(repo, 'a1b2c3d4e5fff1b2c3d4e5f6')
322
+ ]
323
+ end
324
+
325
+ def commit(_repo, sha)
326
+ {
327
+ sha:,
328
+ stats: {
329
+ total: 123
330
+ }
331
+ }
332
+ end
333
+
292
334
  def issue_timeline(_repo, _issue, _options = {})
293
335
  [
294
336
  {
data/lib/fbe.rb CHANGED
@@ -27,5 +27,5 @@
27
27
  # License:: MIT
28
28
  module Fbe
29
29
  # Current version of the gem (changed by .rultor.yml on every release)
30
- VERSION = '0.0.31'
30
+ VERSION = '0.0.33'
31
31
  end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ # MIT License
4
+ #
5
+ # Copyright (c) 2024 Zerocracy
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ # of this software and associated documentation files (the "Software"), to deal
9
+ # in the Software without restriction, including without limitation the rights
10
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ # copies of the Software, and to permit persons to whom the Software is
12
+ # furnished to do so, subject to the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be included in all
15
+ # copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ # SOFTWARE.
24
+
25
+ require 'minitest/autorun'
26
+ require 'faraday'
27
+ require 'logger'
28
+ require_relative '../../../lib/fbe/middleware'
29
+
30
+ class QuotaTest < Minitest::Test
31
+ class FakeApp
32
+ def initialize
33
+ @calls = 0
34
+ end
35
+
36
+ def call(env)
37
+ @calls += 1
38
+ response_headers = {
39
+ 'x-ratelimit-remaining' => (100 - @calls).to_s
40
+ }
41
+ env[:response_headers] = response_headers
42
+ env
43
+ end
44
+ end
45
+
46
+ def test_quota_middleware_pauses_when_quota_low
47
+ loog = Loog::NULL
48
+ pause = 0
49
+ app = FakeApp.new
50
+ middleware = Fbe::Middleware::Quota.new(app, logger: loog, pause:)
51
+ start_time = Time.now
52
+ 105.times do
53
+ env = Judges::Options.new(
54
+ 'method' => :get,
55
+ 'url' => 'http://example.com',
56
+ 'request_headers' => {},
57
+ 'response_headers' => {}
58
+ )
59
+ middleware.call(env)
60
+ end
61
+ assert_in_delta pause, Time.now - start_time, 0.4
62
+ end
63
+
64
+ def test_quota_middleware_logs_when_quota_low
65
+ pause = 1
66
+ log_output = StringIO.new
67
+ loog = Logger.new(log_output)
68
+ app = FakeApp.new
69
+ middleware = Fbe::Middleware::Quota.new(app, logger: loog, pause:)
70
+ 105.times do
71
+ env = Judges::Options.new(
72
+ 'method' => :get,
73
+ 'url' => 'http://example.com',
74
+ 'request_headers' => {},
75
+ 'response_headers' => {}
76
+ )
77
+ middleware.call(env)
78
+ end
79
+ assert_match(/Too much GitHub API quota/, log_output.string)
80
+ end
81
+ end
@@ -117,4 +117,31 @@ class TestOcto < Minitest::Test
117
117
  assert_equal(1, o.commit_pulls('zerocracy/fbe', '0b7d0699bd744b62c0731064c2adaad0c58e1416').size)
118
118
  assert_equal(0, o.commit_pulls('zerocracy/fbe', '16b3ea6b71c6e932ba7666c40ca846ecaa6d6f0d').size)
119
119
  end
120
+
121
+ def test_pauses_when_quota_is_exceeded
122
+ WebMock.disable_net_connect!
123
+ global = {}
124
+ pause = 1
125
+ o = Fbe.octo(loog: Loog::NULL, global:, options: Judges::Options.new({ 'github_api_pause' => pause }))
126
+ limit = 100
127
+ start_time = Time.now
128
+ 105.times do |i|
129
+ n = i + 1
130
+ user = "test#{n}"
131
+ limit = 100 if n > 100
132
+ stub_request(:get, "https://api.github.com/users/#{user}")
133
+ .then
134
+ .to_return(
135
+ status: 200, body: '{}',
136
+ headers: {
137
+ 'x-ratelimit-remaining' => limit.to_s
138
+ }
139
+ )
140
+ .times(1)
141
+ o.user(user)
142
+ assert(!o.off_quota) if n > 100
143
+ limit -= 1
144
+ end
145
+ assert_in_delta(pause, Time.now - start_time, 0.4)
146
+ end
120
147
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fbe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.31
4
+ version: 0.0.33
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko
@@ -230,12 +230,15 @@ files:
230
230
  - lib/fbe/if_absent.rb
231
231
  - lib/fbe/issue.rb
232
232
  - lib/fbe/iterate.rb
233
+ - lib/fbe/middleware.rb
234
+ - lib/fbe/middleware/quota.rb
233
235
  - lib/fbe/octo.rb
234
236
  - lib/fbe/sec.rb
235
237
  - lib/fbe/unmask_repos.rb
236
238
  - lib/fbe/who.rb
237
239
  - renovate.json
238
240
  - rules/basic.fe
241
+ - test/fbe/middleware/test_quota.rb
239
242
  - test/fbe/test_award.rb
240
243
  - test/fbe/test_conclude.rb
241
244
  - test/fbe/test_fb.rb