fbe 0.6.0 → 0.7.0

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: 72f0ba759db6bd1370f62c85290d009b0253b1c2d0b67f6933a6b8e2b43817ef
4
- data.tar.gz: c7b030938e82ec475316cd1e4ffcf3597fe26665020114c9e8f847741853b1b4
3
+ metadata.gz: af8e39332315cd637642316ea61761792955d43688813b75339b112b58747900
4
+ data.tar.gz: 6a2fa9d6c135c1ec2500872ace2bba09d00a89fe87c1af6435e54e880f361df4
5
5
  SHA512:
6
- metadata.gz: edf889e94309ab5ebd1e0760a2152bc546d44b0b8ba42df2e5b4394cbabbc3964819690d787434bf10570a55ba3ed97514516ab029fe200056996994077fe00a
7
- data.tar.gz: 45ce296b829c75109fd3a4f92f7b5f1ace1d3e77062210b0aa0214b2a7939509b9bddc95f5363d8d05f2a288484b2ada461695326b2284fe0fab8d745138ee17
6
+ metadata.gz: 94a48b37c3d821a8c609e99accfc1fb350b1e317f2cb27c7d351a8a472ff1565edec77d4a3bd2a1d39c758c8e6faa71e5706a1a30fe0364bceffd25144466642
7
+ data.tar.gz: 8073b49266007c50ae6989ffb1b006fbcddce056cb042be19f5ca39c4e99ad97b58ad77c598d51102b51ef77b9545a4f86fd29cf0323edb7fee9920ff6e65227
data/Gemfile CHANGED
@@ -17,5 +17,6 @@ gem 'rubocop-performance', '>0', require: false
17
17
  gem 'rubocop-rake', '>0', require: false
18
18
  gem 'simplecov', '~>0.22', require: false
19
19
  gem 'simplecov-cobertura', '~>2.1', require: false
20
+ gem 'veils', '>0', require: false
20
21
  gem 'webmock', '~>3.25', require: false
21
22
  gem 'yard', '~>0.9', require: false
data/Gemfile.lock CHANGED
@@ -99,7 +99,7 @@ GEM
99
99
  fiber-storage (1.0.0)
100
100
  gli (2.22.2)
101
101
  ostruct
102
- graphql (2.5.2)
102
+ graphql (2.5.3)
103
103
  base64
104
104
  fiber-storage
105
105
  logger
@@ -158,7 +158,7 @@ GEM
158
158
  os (1.1.4)
159
159
  ostruct (0.6.1)
160
160
  others (0.0.3)
161
- parallel (1.26.3)
161
+ parallel (1.27.0)
162
162
  parser (3.3.8.0)
163
163
  ast (~> 2.4.1)
164
164
  racc
@@ -225,6 +225,7 @@ GEM
225
225
  unicode-emoji (~> 4.0, >= 4.0.4)
226
226
  unicode-emoji (4.0.4)
227
227
  uri (1.0.3)
228
+ veils (0.4.0)
228
229
  verbose (0.0.2)
229
230
  loog (~> 0.2)
230
231
  tago (~> 0.0)
@@ -257,6 +258,7 @@ DEPENDENCIES
257
258
  rubocop-rake (> 0)
258
259
  simplecov (~> 0.22)
259
260
  simplecov-cobertura (~> 2.1)
261
+ veils (> 0)
260
262
  webmock (~> 3.25)
261
263
  yard (~> 0.9)
262
264
 
data/Rakefile CHANGED
@@ -16,8 +16,6 @@ def version
16
16
  Gem::Specification.load(Dir['*.gemspec'].first).version
17
17
  end
18
18
 
19
- ENV['RACK_ENV'] = 'test'
20
-
21
19
  task default: %i[clean test picks rubocop yard]
22
20
 
23
21
  require 'rake/testtask'
data/lib/fbe/iterate.rb CHANGED
@@ -107,11 +107,23 @@ class Fbe::Iterate
107
107
  raise 'Use "by" first' if @query.nil?
108
108
  seen = {}
109
109
  oct = Fbe.octo(loog: @loog, options: @options, global: @global)
110
+ if oct.off_quota
111
+ @loog.debug('We are off GitHub quota, cannot even start, sorry')
112
+ return
113
+ end
110
114
  repos = Fbe.unmask_repos(loog: @loog, options: @options, global: @global)
111
115
  restarted = []
112
116
  start = Time.now
113
117
  loop do
118
+ if oct.off_quota
119
+ @loog.info("We are off GitHub quota, time to stop after #{start.ago}")
120
+ break
121
+ end
114
122
  repos.each do |repo|
123
+ if oct.off_quota
124
+ @loog.debug("We are off GitHub quota, we must skip #{repo}")
125
+ break
126
+ end
115
127
  if Time.now - start > timeout
116
128
  $loog.info("We are doing this for #{start.ago} already, won't check #{repo}")
117
129
  next
@@ -152,14 +164,6 @@ class Fbe::Iterate
152
164
  end
153
165
  f.what = @label
154
166
  seen[repo] += 1
155
- if oct.off_quota
156
- @loog.debug('We are off GitHub quota, time to stop')
157
- break
158
- end
159
- end
160
- if oct.off_quota
161
- @loog.info("We are off GitHub quota, time to stop after #{start.ago}")
162
- break
163
167
  end
164
168
  unless seen.any? { |r, v| v < @repeats && !restarted.include?(r) }
165
169
  @loog.debug("No more repos to scan (out of #{repos.size}), quitting after #{start.ago}")
data/lib/fbe/octo.rb CHANGED
@@ -13,7 +13,6 @@ require 'verbose'
13
13
  require_relative '../fbe'
14
14
  require_relative 'middleware'
15
15
  require_relative 'middleware/formatter'
16
- require_relative 'middleware/quota'
17
16
 
18
17
  # Makes a call to the GitHub API.
19
18
  #
@@ -71,7 +70,6 @@ def Fbe.octo(options: $options, global: $global, loog: $loog)
71
70
  methods: [:get],
72
71
  backoff_factor: 2
73
72
  )
74
- builder.use(Fbe::Middleware::Quota, loog:, pause: options.github_api_pause || 60)
75
73
  builder.use(Faraday::HttpCache, serializer: Marshal, shared_cache: false, logger: Loog::NULL)
76
74
  builder.use(Octokit::Response::RaiseError)
77
75
  builder.use(Faraday::Response::Logger, loog, formatter: Fbe::Middleware::Formatter)
@@ -84,10 +82,10 @@ def Fbe.octo(options: $options, global: $global, loog: $loog)
84
82
  o = Fbe::FakeOctokit.new
85
83
  end
86
84
  decoor(o, loog:) do
87
- def off_quota
85
+ def off_quota(threshold: 50)
88
86
  left = @origin.rate_limit.remaining
89
- if left < 5
90
- @loog.info("Too much GitHub API quota consumed already (remaining=#{left}), stopping")
87
+ if left < threshold
88
+ @loog.info("Too much GitHub API quota consumed already (#{left} < #{threshold}), stopping")
91
89
  true
92
90
  else
93
91
  false
data/lib/fbe.rb CHANGED
@@ -10,5 +10,5 @@
10
10
  # License:: MIT
11
11
  module Fbe
12
12
  # Current version of the gem (changed by +.rultor.yml+ on every release)
13
- VERSION = '0.6.0' unless const_defined?(:VERSION)
13
+ VERSION = '0.7.0' unless const_defined?(:VERSION)
14
14
  end
@@ -133,29 +133,20 @@ class TestOcto < Fbe::Test
133
133
 
134
134
  def test_pauses_when_quota_is_exceeded
135
135
  WebMock.disable_net_connect!
136
- global = {}
137
- pause = 0.1
138
- o = Fbe.octo(loog: Loog::NULL, global:, options: Judges::Options.new({ 'github_api_pause' => pause }))
139
- limit = 100
140
- start_time = Time.now
141
- 105.times do |i|
142
- n = i + 1
143
- user = "test#{n}"
144
- limit = 100 if n > 100
145
- stub_request(:get, "https://api.github.com/users/#{user}")
146
- .then
147
- .to_return(
148
- status: 200, body: '{}',
149
- headers: {
150
- 'x-ratelimit-remaining' => limit.to_s
151
- }
152
- )
153
- .times(1)
154
- o.user(user)
155
- refute(o.off_quota) if n > 100
156
- limit -= 1
157
- end
158
- assert_in_delta(pause, Time.now - start_time, 5)
136
+ o = Fbe.octo(loog: Loog::NULL, global: {}, options: Judges::Options.new({ 'github_api_pause' => 0.01 }))
137
+ stub_request(:get, 'https://api.github.com/users/foo')
138
+ .to_return(
139
+ status: 200, body: '{}',
140
+ headers: { 'x-ratelimit-remaining' => '1' }
141
+ )
142
+ .to_return(
143
+ status: 200, body: '{}',
144
+ headers: { 'x-ratelimit-remaining' => '10000' }
145
+ )
146
+ o.user('foo')
147
+ assert(o.off_quota)
148
+ o.user('foo')
149
+ refute(o.off_quota)
159
150
  end
160
151
 
161
152
  def test_fetches_fake_check_runs_for_ref
@@ -193,4 +184,10 @@ class TestOcto < Fbe::Test
193
184
  result = o.workflow_run_job('zerocracy/baza', 0)
194
185
  assert_equal(0, result[:id])
195
186
  end
187
+
188
+ def test_reads_quota
189
+ WebMock.enable_net_connect!
190
+ o = Fbe.octo(loog: Loog::VERBOSE, global: {}, options: Judges::Options.new({ 'github_api_pause' => 0.01 }))
191
+ refute_nil(o.off_quota)
192
+ end
196
193
  end
data/test/test__helper.rb CHANGED
@@ -5,6 +5,8 @@
5
5
 
6
6
  $stdout.sync = true
7
7
 
8
+ ENV['RACK_ENV'] = 'test'
9
+
8
10
  require 'simplecov'
9
11
  require 'simplecov-cobertura'
10
12
  unless SimpleCov.running || ARGV.include?('--no-cov')
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fbe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-04-14 00:00:00.000000000 Z
10
+ date: 2025-04-15 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: backtrace
@@ -305,7 +305,6 @@ files:
305
305
  - lib/fbe/just_one.rb
306
306
  - lib/fbe/middleware.rb
307
307
  - lib/fbe/middleware/formatter.rb
308
- - lib/fbe/middleware/quota.rb
309
308
  - lib/fbe/octo.rb
310
309
  - lib/fbe/overwrite.rb
311
310
  - lib/fbe/pmp.rb
@@ -317,7 +316,6 @@ files:
317
316
  - renovate.json
318
317
  - rules/basic.fe
319
318
  - test/fbe/middleware/test_formatter.rb
320
- - test/fbe/middleware/test_quota.rb
321
319
  - test/fbe/test_award.rb
322
320
  - test/fbe/test_bylaws.rb
323
321
  - test/fbe/test_conclude.rb
@@ -1,64 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # SPDX-FileCopyrightText: Copyright (c) 2024-2025 Zerocracy
4
- # SPDX-License-Identifier: MIT
5
-
6
- require 'faraday'
7
- require_relative '../middleware'
8
-
9
- # Faraday Middleware that monitors GitHub API rate limits.
10
- #
11
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
12
- # Copyright:: Copyright (c) 2024-2025 Zerocracy
13
- # License:: MIT
14
- class Fbe::Middleware::Quota < Faraday::Middleware
15
- # Constructor.
16
- #
17
- # @param [Object] app The Faraday app
18
- # @param [Loog] loog The logging facility
19
- # @param [Integer] pause Seconds to pause when rate limit is reached
20
- # @param [Integer] limit Maximum number of requests before checking rate limit
21
- # @param [Integer] rate Minimum remaining requests threshold
22
- def initialize(app, loog: Loog::NULL, pause: 60, limit: 100, rate: 5)
23
- super(app)
24
- @requests = 0
25
- @app = app
26
- raise 'The "loog" cannot be nil' if loog.nil?
27
- @loog = loog
28
- raise 'The "pause" cannot be nil' if pause.nil?
29
- raise 'The "pause" must be a positive integer' unless pause.positive?
30
- @pause = pause
31
- raise 'The "limit" cannot be nil' if limit.nil?
32
- raise 'The "limit" must be a positive integer' unless limit.positive?
33
- @limit = limit
34
- raise 'The "rate" cannot be nil' if rate.nil?
35
- raise 'The "rate" must be a positive integer' unless rate.positive?
36
- @rate = rate
37
- end
38
-
39
- # Process the request and handle rate limiting.
40
- #
41
- # @param [Faraday::Env] env The environment
42
- # @return [Faraday::Response] The response
43
- def call(env)
44
- @requests += 1
45
- response = @app.call(env)
46
- if out_of_limit?(env)
47
- @loog.info("Too much GitHub API quota consumed, pausing for #{@pause} seconds")
48
- sleep(@pause)
49
- @requests = 0
50
- end
51
- response
52
- end
53
-
54
- private
55
-
56
- # Check if we're approaching the rate limit.
57
- #
58
- # @param [Faraday::Env] env The environment
59
- # @return [Boolean] True if we should pause to avoid hitting rate limits
60
- def out_of_limit?(env)
61
- remaining = env.response_headers['x-ratelimit-remaining'].to_i
62
- (@requests % @limit).zero? && remaining < @rate
63
- end
64
- end
@@ -1,66 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # SPDX-FileCopyrightText: Copyright (c) 2024-2025 Zerocracy
4
- # SPDX-License-Identifier: MIT
5
-
6
- require 'faraday'
7
- require 'logger'
8
- require 'loog'
9
- require 'judges'
10
- require 'judges/options'
11
- require_relative '../../../lib/fbe/middleware'
12
- require_relative '../../../lib/fbe/middleware/quota'
13
- require_relative '../../test__helper'
14
-
15
- class QuotaTest < Fbe::Test
16
- class FakeApp
17
- def initialize
18
- @calls = 0
19
- end
20
-
21
- def call(env)
22
- @calls += 1
23
- response_headers = {
24
- 'x-ratelimit-remaining' => (100 - @calls).to_s
25
- }
26
- env[:response_headers] = response_headers
27
- env
28
- end
29
- end
30
-
31
- def test_quota_middleware_pauses_when_quota_low
32
- loog = Loog::NULL
33
- pause = 0.1
34
- app = FakeApp.new
35
- middleware = Fbe::Middleware::Quota.new(app, loog:, pause:)
36
- start_time = Time.now
37
- 105.times do
38
- env = Judges::Options.new(
39
- 'method' => :get,
40
- 'url' => 'http://example.com',
41
- 'request_headers' => {},
42
- 'response_headers' => {}
43
- )
44
- middleware.call(env)
45
- end
46
- assert_in_delta pause, Time.now - start_time, 0.4
47
- end
48
-
49
- def test_quota_middleware_logs_when_quota_low
50
- pause = 0.1
51
- log_output = StringIO.new
52
- loog = Logger.new(log_output)
53
- app = FakeApp.new
54
- middleware = Fbe::Middleware::Quota.new(app, loog:, pause:)
55
- 105.times do
56
- env = Judges::Options.new(
57
- 'method' => :get,
58
- 'url' => 'http://example.com',
59
- 'request_headers' => {},
60
- 'response_headers' => {}
61
- )
62
- middleware.call(env)
63
- end
64
- assert_match(/Too much GitHub API quota/, log_output.string)
65
- end
66
- end