fbe 0.5.1 → 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: 27b96e4e39ce6a637b696b09e9cbadf4a568808a09a346cf047829177159b7e4
4
- data.tar.gz: dedbe3927aa65537bd018d99c12dd946feaf24e18149b32c0c09b92eef27990c
3
+ metadata.gz: af8e39332315cd637642316ea61761792955d43688813b75339b112b58747900
4
+ data.tar.gz: 6a2fa9d6c135c1ec2500872ace2bba09d00a89fe87c1af6435e54e880f361df4
5
5
  SHA512:
6
- metadata.gz: 4c8c8cdc56cdd98315a73fa6f9fc918a17a15df7bcb0098389265898ee900cc2b4306f6f8ffe1589018a4ca6f081081dab8660e02afcc95ce52ea5bc6566f4ab
7
- data.tar.gz: '0880f2cf0795093280b210c4b891ea9eb7e7c9a928bbfdd324b497da40a4d20a80d190ce4afd08ace605b9e14a74275b5aa82dc1a0a623337e252ab1ec27accc'
6
+ metadata.gz: 94a48b37c3d821a8c609e99accfc1fb350b1e317f2cb27c7d351a8a472ff1565edec77d4a3bd2a1d39c758c8e6faa71e5706a1a30fe0364bceffd25144466642
7
+ data.tar.gz: 8073b49266007c50ae6989ffb1b006fbcddce056cb042be19f5ca39c4e99ad97b58ad77c598d51102b51ef77b9545a4f86fd29cf0323edb7fee9920ff6e65227
data/Gemfile CHANGED
@@ -15,8 +15,8 @@ gem 'rubocop', '~>1.75', require: false
15
15
  gem 'rubocop-minitest', '>0', require: false
16
16
  gem 'rubocop-performance', '>0', require: false
17
17
  gem 'rubocop-rake', '>0', require: false
18
- gem 'rubocop-rspec', '>0', require: false
19
18
  gem 'simplecov', '~>0.22', require: false
20
19
  gem 'simplecov-cobertura', '~>2.1', require: false
20
+ gem 'veils', '>0', require: false
21
21
  gem 'webmock', '~>3.25', require: false
22
22
  gem 'yard', '~>0.9', require: false
data/Gemfile.lock CHANGED
@@ -17,6 +17,7 @@ PATH
17
17
  obk (~> 0)
18
18
  octokit (~> 9)
19
19
  others (~> 0)
20
+ tago (~> 0)
20
21
  verbose (~> 0)
21
22
 
22
23
  GEM
@@ -41,7 +42,7 @@ GEM
41
42
  ast (2.4.3)
42
43
  backtrace (0.4.0)
43
44
  base64 (0.2.0)
44
- baza.rb (0.1.0)
45
+ baza.rb (0.4.0)
45
46
  backtrace (> 0)
46
47
  elapsed (> 0)
47
48
  faraday (> 0)
@@ -79,7 +80,7 @@ GEM
79
80
  others (~> 0.0)
80
81
  tago (~> 0.0)
81
82
  yaml (~> 0.3)
82
- faraday (2.12.2)
83
+ faraday (2.13.0)
83
84
  faraday-net_http (>= 2.0, < 3.5)
84
85
  json
85
86
  logger
@@ -98,7 +99,7 @@ GEM
98
99
  fiber-storage (1.0.0)
99
100
  gli (2.22.2)
100
101
  ostruct
101
- graphql (2.5.1)
102
+ graphql (2.5.3)
102
103
  base64
103
104
  fiber-storage
104
105
  logger
@@ -157,8 +158,8 @@ GEM
157
158
  os (1.1.4)
158
159
  ostruct (0.6.1)
159
160
  others (0.0.3)
160
- parallel (1.26.3)
161
- parser (3.3.7.4)
161
+ parallel (1.27.0)
162
+ parser (3.3.8.0)
162
163
  ast (~> 2.4.1)
163
164
  racc
164
165
  prism (1.4.0)
@@ -185,7 +186,7 @@ GEM
185
186
  rubocop-ast (>= 1.44.0, < 2.0)
186
187
  ruby-progressbar (~> 1.7)
187
188
  unicode-display_width (>= 2.4.0, < 4.0)
188
- rubocop-ast (1.44.0)
189
+ rubocop-ast (1.44.1)
189
190
  parser (>= 3.3.7.2)
190
191
  prism (~> 1.4)
191
192
  rubocop-minitest (0.38.0)
@@ -199,9 +200,6 @@ GEM
199
200
  rubocop-rake (0.7.1)
200
201
  lint_roller (~> 1.1)
201
202
  rubocop (>= 1.72.1)
202
- rubocop-rspec (3.5.0)
203
- lint_roller (~> 1.1)
204
- rubocop (~> 1.72, >= 1.72.1)
205
203
  ruby-progressbar (1.13.0)
206
204
  sawyer (0.9.2)
207
205
  addressable (>= 2.3.5)
@@ -227,6 +225,7 @@ GEM
227
225
  unicode-emoji (~> 4.0, >= 4.0.4)
228
226
  unicode-emoji (4.0.4)
229
227
  uri (1.0.3)
228
+ veils (0.4.0)
230
229
  verbose (0.0.2)
231
230
  loog (~> 0.2)
232
231
  tago (~> 0.0)
@@ -257,9 +256,9 @@ DEPENDENCIES
257
256
  rubocop-minitest (> 0)
258
257
  rubocop-performance (> 0)
259
258
  rubocop-rake (> 0)
260
- rubocop-rspec (> 0)
261
259
  simplecov (~> 0.22)
262
260
  simplecov-cobertura (~> 2.1)
261
+ veils (> 0)
263
262
  webmock (~> 3.25)
264
263
  yard (~> 0.9)
265
264
 
data/README.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # FactBase Extended (FBE)
2
2
 
3
- [![DevOps By Rultor.com](http://www.rultor.com/b/zerocracy/fbe)](http://www.rultor.com/p/zerocracy/fbe)
3
+ [![DevOps By Rultor.com](https://www.rultor.com/b/zerocracy/fbe)](https://www.rultor.com/p/zerocracy/fbe)
4
4
 
5
5
  [![rake](https://github.com/zerocracy/fbe/actions/workflows/rake.yml/badge.svg)](https://github.com/zerocracy/fbe/actions/workflows/rake.yml)
6
- [![PDD status](http://www.0pdd.com/svg?name=zerocracy/fbe)](http://www.0pdd.com/p?name=zerocracy/fbe)
7
- [![Gem Version](https://badge.fury.io/rb/fbe.svg)](http://badge.fury.io/rb/fbe)
6
+ [![PDD status](https://www.0pdd.com/svg?name=zerocracy/fbe)](https://www.0pdd.com/p?name=zerocracy/fbe)
7
+ [![Gem Version](https://badge.fury.io/rb/fbe.svg)](https://badge.fury.io/rb/fbe)
8
8
  [![Test Coverage](https://img.shields.io/codecov/c/github/zerocracy/fbe.svg)](https://codecov.io/github/zerocracy/fbe?branch=master)
9
- [![Yard Docs](http://img.shields.io/badge/yard-docs-blue.svg)](http://rubydoc.info/github/zerocracy/fbe/master/frames)
9
+ [![Yard Docs](https://img.shields.io/badge/yard-docs-blue.svg)](https://rubydoc.info/github/zerocracy/fbe/master/frames)
10
10
  [![Hits-of-Code](https://hitsofcode.com/github/zerocracy/fbe)](https://hitsofcode.com/view/github/zerocracy/fbe)
11
11
  [![License](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/zerocracy/fbe/blob/master/LICENSE.txt)
12
12
 
data/Rakefile CHANGED
@@ -16,14 +16,11 @@ 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'
24
22
  desc 'Run all unit tests'
25
23
  Rake::TestTask.new(:test) do |test|
26
- Rake::Cleaner.cleanup_files(['coverage'])
27
24
  test.libs << 'lib' << 'test'
28
25
  test.pattern = 'test/**/test_*.rb'
29
26
  test.warning = true
@@ -33,7 +30,7 @@ end
33
30
  desc 'Run them via Ruby, one by one'
34
31
  task :picks do
35
32
  (Dir['test/**/*.rb'] + Dir['lib/**/*.rb']).each do |f|
36
- qbash("bundle exec ruby #{Shellwords.escape(f)}", log: $stdout, env: { 'RACK_ENV' => 'picks' })
33
+ qbash("bundle exec ruby #{Shellwords.escape(f)} -- --no-cov", log: $stdout)
37
34
  end
38
35
  end
39
36
 
data/fbe.gemspec CHANGED
@@ -37,6 +37,7 @@ Gem::Specification.new do |s|
37
37
  s.add_dependency 'obk', '~>0'
38
38
  s.add_dependency 'octokit', '~>9'
39
39
  s.add_dependency 'others', '~>0'
40
+ s.add_dependency 'tago', '~>0'
40
41
  s.add_dependency 'verbose', '~>0'
41
42
  s.metadata['rubygems_mfa_required'] = 'true'
42
43
  end
data/lib/fbe/conclude.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  # SPDX-FileCopyrightText: Copyright (c) 2024-2025 Zerocracy
4
4
  # SPDX-License-Identifier: MIT
5
5
 
6
+ require 'tago'
6
7
  require_relative '../fbe'
7
8
  require_relative 'fb'
8
9
  require_relative 'octo'
@@ -61,6 +62,7 @@ class Fbe::Conclude
61
62
  @query = nil
62
63
  @follows = []
63
64
  @quota_aware = false
65
+ @timeout = 60
64
66
  end
65
67
 
66
68
  # Make this block aware of GitHub API quota.
@@ -74,6 +76,17 @@ class Fbe::Conclude
74
76
  @quota_aware = true
75
77
  end
76
78
 
79
+ # Make sure this block runs for less than allowed amount of seconds.
80
+ #
81
+ # When the quota is reached, the loop will gracefully stop to avoid.
82
+ # This helps prevent interruptions in long-running operations.
83
+ #
84
+ # @param [Float] sec Seconds
85
+ # @return [nil] Nothing is returned
86
+ def timeout(sec)
87
+ @timeout = sec
88
+ end
89
+
77
90
  # Set the query that should find the facts in the factbase.
78
91
  #
79
92
  # @param [String] query The query to execute
@@ -146,10 +159,18 @@ class Fbe::Conclude
146
159
  # @return [Integer] The count of the facts seen
147
160
  def roll(&)
148
161
  passed = 0
162
+ start = Time.now
149
163
  catch :stop do
150
164
  @fb.txn do |fbt|
151
165
  fbt.query(@query).each do |a|
152
- throw :stop if @quota_aware && Fbe.octo(loog: @loog, options: @options, global: @global).off_quota
166
+ if @quota_aware && Fbe.octo(loog: @loog, options: @options, global: @global).off_quota
167
+ @loog.debug('We ran out of GitHub quota, must stop here')
168
+ throw :stop
169
+ end
170
+ if Time.now > start + @timeout
171
+ @loog.debug("We've spent more than #{start.ago}, must stop here")
172
+ throw :stop
173
+ end
153
174
  n = yield fbt, a
154
175
  @loog.info("#{n.what}: #{n.details}") unless n.nil?
155
176
  passed += 1
@@ -32,13 +32,11 @@ end
32
32
  class Fbe::Graph
33
33
  def initialize(token:, host: 'api.github.com')
34
34
  @token = token
35
- http = HTTP.new(token, host)
36
- @client = GraphQL::Client.new(schema: GraphQL::Client.load_schema(http), execute: http)
37
- @client.allow_dynamic_queries = true
35
+ @host = host
38
36
  end
39
37
 
40
- def query(query_string)
41
- result = @client.query(@client.parse(query_string))
38
+ def query(qry)
39
+ result = client.query(client.parse(qry))
42
40
  result.data
43
41
  end
44
42
 
@@ -116,6 +114,19 @@ class Fbe::Graph
116
114
  }
117
115
  end
118
116
 
117
+ private
118
+
119
+ def client
120
+ @client ||=
121
+ begin
122
+ http = HTTP.new(@token, @host)
123
+ schema = GraphQL::Client.load_schema(http)
124
+ c = GraphQL::Client.new(schema:, execute: http)
125
+ c.allow_dynamic_queries = true
126
+ c
127
+ end
128
+ end
129
+
119
130
  # The HTTP class
120
131
  class HTTP < GraphQL::Client::HTTP
121
132
  def initialize(token, host)
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/sec.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  # SPDX-FileCopyrightText: Copyright (c) 2024-2025 Zerocracy
4
4
  # SPDX-License-Identifier: MIT
5
5
 
6
+ require 'tago'
6
7
  require_relative '../fbe'
7
8
 
8
9
  # Converts number of seconds into text.
@@ -18,15 +19,5 @@ def Fbe.sec(fact, prop = :seconds)
18
19
  s = fact[prop.to_s]
19
20
  raise "There is no #{prop.inspect} property" if s.nil?
20
21
  s = s.first.to_i
21
- if s < 60
22
- format('%d seconds', s)
23
- elsif s < 60 * 60
24
- format('%d minutes', s / 60)
25
- elsif s < 60 * 60 * 24
26
- format('%d hours', s / (60 * 60))
27
- elsif s < 7 * 60 * 60 * 24
28
- format('%d days', s / (60 * 60 * 24))
29
- else
30
- format('%d weeks', s / (7 * 60 * 60 * 24))
31
- end
22
+ (Time.now + s).ago
32
23
  end
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.5.1' unless const_defined?(:VERSION)
13
+ VERSION = '0.7.0' unless const_defined?(:VERSION)
14
14
  end
@@ -14,7 +14,7 @@ require_relative '../../../lib/fbe/middleware/formatter'
14
14
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
15
15
  # Copyright:: Copyright (c) 2024-2025 Zerocracy
16
16
  # License:: MIT
17
- class LoggingFormatterTest < Minitest::Test
17
+ class LoggingFormatterTest < Fbe::Test
18
18
  def test_success_response
19
19
  log_it(status: 200) do |loog|
20
20
  assert_empty(loog.to_s)
@@ -4,14 +4,14 @@
4
4
  # SPDX-License-Identifier: MIT
5
5
 
6
6
  require 'loog'
7
- require_relative '../test__helper'
8
7
  require_relative '../../lib/fbe/award'
8
+ require_relative '../test__helper'
9
9
 
10
10
  # Test.
11
11
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
12
12
  # Copyright:: Copyright (c) 2024 Yegor Bugayenko
13
13
  # License:: MIT
14
- class TestAward < Minitest::Test
14
+ class TestAward < Fbe::Test
15
15
  def test_simple
16
16
  a = Fbe::Award.new(
17
17
  '
@@ -4,15 +4,15 @@
4
4
  # SPDX-License-Identifier: MIT
5
5
 
6
6
  require 'loog'
7
- require_relative '../test__helper'
8
7
  require_relative '../../lib/fbe/award'
9
8
  require_relative '../../lib/fbe/bylaws'
9
+ require_relative '../test__helper'
10
10
 
11
11
  # Test.
12
12
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
13
13
  # Copyright:: Copyright (c) 2024 Yegor Bugayenko
14
14
  # License:: MIT
15
- class TestBylaws < Minitest::Test
15
+ class TestBylaws < Fbe::Test
16
16
  def test_simple
17
17
  laws = Fbe.bylaws
18
18
  assert_operator(laws.size, :>, 1)
@@ -3,19 +3,19 @@
3
3
  # SPDX-FileCopyrightText: Copyright (c) 2024-2025 Zerocracy
4
4
  # SPDX-License-Identifier: MIT
5
5
 
6
- require 'loog'
7
6
  require 'factbase'
8
7
  require 'factbase/syntax'
9
8
  require 'judges/options'
10
- require_relative '../test__helper'
9
+ require 'loog'
11
10
  require_relative '../../lib/fbe/conclude'
12
11
  require_relative '../../lib/fbe/fb'
12
+ require_relative '../test__helper'
13
13
 
14
14
  # Test.
15
15
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
16
16
  # Copyright:: Copyright (c) 2024-2025 Zerocracy
17
17
  # License:: MIT
18
- class TestConclude < Minitest::Test
18
+ class TestConclude < Fbe::Test
19
19
  def test_with_defaults
20
20
  $fb = Factbase.new
21
21
  $global = {}
@@ -4,14 +4,14 @@
4
4
  # SPDX-License-Identifier: MIT
5
5
 
6
6
  require 'factbase'
7
- require_relative '../test__helper'
8
7
  require_relative '../../lib/fbe/copy'
8
+ require_relative '../test__helper'
9
9
 
10
10
  # Test.
11
11
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
12
12
  # Copyright:: Copyright (c) 2024-2025 Zerocracy
13
13
  # License:: MIT
14
- class TestCopy < Minitest::Test
14
+ class TestCopy < Fbe::Test
15
15
  def test_simple_copy
16
16
  fb = Factbase.new
17
17
  f1 = fb.insert
@@ -4,14 +4,14 @@
4
4
  # SPDX-License-Identifier: MIT
5
5
 
6
6
  require 'factbase'
7
- require_relative '../test__helper'
8
7
  require_relative '../../lib/fbe/delete'
8
+ require_relative '../test__helper'
9
9
 
10
10
  # Test.
11
11
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
12
12
  # Copyright:: Copyright (c) 2024-2025 Zerocracy
13
13
  # License:: MIT
14
- class TestDelete < Minitest::Test
14
+ class TestDelete < Fbe::Test
15
15
  def test_deletes_one_property
16
16
  fb = Factbase.new
17
17
  f = fb.insert
@@ -13,7 +13,7 @@ require_relative '../test__helper'
13
13
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
14
14
  # Copyright:: Copyright (c) 2024-2025 Zerocracy
15
15
  # License:: MIT
16
- class TestEnter < Minitest::Test
16
+ class TestEnter < Fbe::Test
17
17
  def test_simple
18
18
  WebMock.disable_net_connect!
19
19
  options = Judges::Options.new({ 'zerocracy_token' => '00000-0000-0000-00000' })
data/test/fbe/test_fb.rb CHANGED
@@ -4,17 +4,17 @@
4
4
  # SPDX-License-Identifier: MIT
5
5
 
6
6
  require 'factbase'
7
- require 'loog'
8
7
  require 'judges/options'
9
- require_relative '../test__helper'
8
+ require 'loog'
10
9
  require_relative '../../lib/fbe'
11
10
  require_relative '../../lib/fbe/fb'
11
+ require_relative '../test__helper'
12
12
 
13
13
  # Test.
14
14
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
15
15
  # Copyright:: Copyright (c) 2024-2025 Zerocracy
16
16
  # License:: MIT
17
- class TestFb < Minitest::Test
17
+ class TestFb < Fbe::Test
18
18
  def test_simple
19
19
  $fb = Factbase.new
20
20
  $global = {}
@@ -13,7 +13,7 @@ require_relative '../../lib/fbe/github_graph'
13
13
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
14
14
  # Copyright:: Copyright (c) 2024-2025 Zerocracy
15
15
  # License:: MIT
16
- class TestGitHubGraph < Minitest::Test
16
+ class TestGitHubGraph < Fbe::Test
17
17
  def test_simple_use
18
18
  WebMock.disable_net_connect!
19
19
  global = {}
@@ -72,6 +72,27 @@ class TestGitHubGraph < Minitest::Test
72
72
  assert_equal(0, result.count)
73
73
  end
74
74
 
75
+ def test_gets_resolved_conversations_via_http
76
+ skip('This test does not work, because the JSON returned is not a valid response from GraphQL')
77
+ WebMock.disallow_net_connect!
78
+ global = {}
79
+ options = Judges::Options.new
80
+ g = Fbe.github_graph(options:, loog: Loog::NULL, global:)
81
+ stub_request(:post, 'https://api.github.com/graphql').to_return(
82
+ body: JSON.pretty_generate(
83
+ {
84
+ data: {
85
+ repository: {
86
+ name: 'foo'
87
+ }
88
+ }
89
+ }
90
+ )
91
+ )
92
+ result = g.resolved_conversations('foo', 'bar', 42)
93
+ assert_equal(1, result.count)
94
+ end
95
+
75
96
  def test_does_not_count_unresolved_conversations
76
97
  skip("it's a live test, run it manually if you need it")
77
98
  WebMock.allow_net_connect!
@@ -13,7 +13,7 @@ require_relative '../../lib/fbe/if_absent'
13
13
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
14
14
  # Copyright:: Copyright (c) 2024-2025 Zerocracy
15
15
  # License:: MIT
16
- class TestIfAbsent < Minitest::Test
16
+ class TestIfAbsent < Fbe::Test
17
17
  def test_ignores
18
18
  fb = Factbase.new
19
19
  fb.insert.foo = 'hello dude'
@@ -13,7 +13,7 @@ require_relative '../test__helper'
13
13
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
14
14
  # Copyright:: Copyright (c) 2024-2025 Zerocracy
15
15
  # License:: MIT
16
- class TestIssue < Minitest::Test
16
+ class TestIssue < Fbe::Test
17
17
  def test_simple
18
18
  fb = Factbase.new
19
19
  f = fb.insert
@@ -3,17 +3,17 @@
3
3
  # SPDX-FileCopyrightText: Copyright (c) 2024-2025 Zerocracy
4
4
  # SPDX-License-Identifier: MIT
5
5
 
6
- require 'loog'
7
6
  require 'factbase'
8
7
  require 'judges/options'
9
- require_relative '../test__helper'
8
+ require 'loog'
10
9
  require_relative '../../lib/fbe/iterate'
10
+ require_relative '../test__helper'
11
11
 
12
12
  # Test.
13
13
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
14
14
  # Copyright:: Copyright (c) 2024-2025 Zerocracy
15
15
  # License:: MIT
16
- class TestIterate < Minitest::Test
16
+ class TestIterate < Fbe::Test
17
17
  def test_simple
18
18
  opts = Judges::Options.new(['repositories=foo/bar', 'testing=true'])
19
19
  fb = Factbase.new
@@ -11,7 +11,7 @@ require_relative '../../lib/fbe/just_one'
11
11
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
12
12
  # Copyright:: Copyright (c) 2024-2025 Zerocracy
13
13
  # License:: MIT
14
- class TestJustOne < Minitest::Test
14
+ class TestJustOne < Fbe::Test
15
15
  def test_ignores
16
16
  fb = Factbase.new
17
17
  fb.insert.foo = 'hello dude'
@@ -4,16 +4,16 @@
4
4
  # SPDX-License-Identifier: MIT
5
5
 
6
6
  require 'judges/options'
7
- require 'webmock/minitest'
8
7
  require 'loog'
9
- require_relative '../test__helper'
8
+ require 'webmock/minitest'
10
9
  require_relative '../../lib/fbe/octo'
10
+ require_relative '../test__helper'
11
11
 
12
12
  # Test.
13
13
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
14
14
  # Copyright:: Copyright (c) 2024-2025 Zerocracy
15
15
  # License:: MIT
16
- class TestOcto < Minitest::Test
16
+ class TestOcto < Fbe::Test
17
17
  def test_simple_use
18
18
  global = {}
19
19
  options = Judges::Options.new({ 'testing' => true })
@@ -133,29 +133,20 @@ class TestOcto < Minitest::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 < Minitest::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
@@ -4,14 +4,14 @@
4
4
  # SPDX-License-Identifier: MIT
5
5
 
6
6
  require 'factbase'
7
- require_relative '../test__helper'
8
7
  require_relative '../../lib/fbe/overwrite'
8
+ require_relative '../test__helper'
9
9
 
10
10
  # Test.
11
11
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
12
12
  # Copyright:: Copyright (c) 2024-2025 Zerocracy
13
13
  # License:: MIT
14
- class TestOverwrite < Minitest::Test
14
+ class TestOverwrite < Fbe::Test
15
15
  def test_simple_overwrite
16
16
  fb = Factbase.new
17
17
  f = fb.insert
data/test/fbe/test_pmp.rb CHANGED
@@ -3,17 +3,17 @@
3
3
  # SPDX-FileCopyrightText: Copyright (c) 2024-2025 Zerocracy
4
4
  # SPDX-License-Identifier: MIT
5
5
 
6
+ require 'factbase'
6
7
  require 'judges/options'
7
8
  require 'loog'
8
- require 'factbase'
9
- require_relative '../test__helper'
10
9
  require_relative '../../lib/fbe/pmp'
10
+ require_relative '../test__helper'
11
11
 
12
12
  # Test.
13
13
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
14
14
  # Copyright:: Copyright (c) 2024-2025 Zerocracy
15
15
  # License:: MIT
16
- class TestPmp < Minitest::Test
16
+ class TestPmp < Fbe::Test
17
17
  def test_defaults
18
18
  $fb = Factbase.new
19
19
  $global = {}
@@ -3,16 +3,16 @@
3
3
  # SPDX-FileCopyrightText: Copyright (c) 2024-2025 Zerocracy
4
4
  # SPDX-License-Identifier: MIT
5
5
 
6
- require 'loog'
7
6
  require 'factbase'
8
- require_relative '../test__helper'
7
+ require 'loog'
9
8
  require_relative '../../lib/fbe/regularly'
9
+ require_relative '../test__helper'
10
10
 
11
11
  # Test.
12
12
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
13
13
  # Copyright:: Copyright (c) 2024-2025 Zerocracy
14
14
  # License:: MIT
15
- class TestRegularly < Minitest::Test
15
+ class TestRegularly < Fbe::Test
16
16
  def test_simple
17
17
  fb = Factbase.new
18
18
  loog = Loog::NULL
@@ -3,17 +3,17 @@
3
3
  # SPDX-FileCopyrightText: Copyright (c) 2024-2025 Zerocracy
4
4
  # SPDX-License-Identifier: MIT
5
5
 
6
- require 'loog'
7
6
  require 'factbase'
8
7
  require 'judges/options'
9
- require_relative '../test__helper'
8
+ require 'loog'
10
9
  require_relative '../../lib/fbe/repeatedly'
10
+ require_relative '../test__helper'
11
11
 
12
12
  # Test.
13
13
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
14
14
  # Copyright:: Copyright (c) 2024-2025 Zerocracy
15
15
  # License:: MIT
16
- class TestRepeatedly < Minitest::Test
16
+ class TestRepeatedly < Fbe::Test
17
17
  def test_simple
18
18
  $fb = Factbase.new
19
19
  $loog = Loog::NULL
data/test/fbe/test_sec.rb CHANGED
@@ -4,18 +4,18 @@
4
4
  # SPDX-License-Identifier: MIT
5
5
 
6
6
  require 'factbase'
7
- require_relative '../test__helper'
8
7
  require_relative '../../lib/fbe/sec'
8
+ require_relative '../test__helper'
9
9
 
10
10
  # Test.
11
11
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
12
12
  # Copyright:: Copyright (c) 2024-2025 Zerocracy
13
13
  # License:: MIT
14
- class TestSec < Minitest::Test
14
+ class TestSec < Fbe::Test
15
15
  def test_simple
16
16
  fb = Factbase.new
17
17
  f = fb.insert
18
18
  f.seconds = 333
19
- assert_equal('5 minutes', Fbe.sec(f))
19
+ assert(Fbe.sec(f).start_with?('5m'))
20
20
  end
21
21
  end
@@ -12,7 +12,7 @@ require_relative '../../lib/fbe/unmask_repos'
12
12
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
13
13
  # Copyright:: Copyright (c) 2024-2025 Zerocracy
14
14
  # License:: MIT
15
- class TestUnmaskRepos < Minitest::Test
15
+ class TestUnmaskRepos < Fbe::Test
16
16
  def test_simple_use
17
17
  opts = Judges::Options.new(
18
18
  {
data/test/fbe/test_who.rb CHANGED
@@ -13,7 +13,7 @@ require_relative '../test__helper'
13
13
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
14
14
  # Copyright:: Copyright (c) 2024-2025 Zerocracy
15
15
  # License:: MIT
16
- class TestWho < Minitest::Test
16
+ class TestWho < Fbe::Test
17
17
  def test_simple
18
18
  fb = Factbase.new
19
19
  f = fb.insert
data/test/test__helper.rb CHANGED
@@ -5,22 +5,36 @@
5
5
 
6
6
  $stdout.sync = true
7
7
 
8
- require 'minitest/reporters'
9
- Minitest::Reporters.use! [Minitest::Reporters::SpecReporter.new]
8
+ ENV['RACK_ENV'] = 'test'
10
9
 
11
- if ENV['RACK_ENV'] == 'test'
12
- require 'simplecov'
13
- require 'simplecov-cobertura'
14
- SimpleCov.formatters = [
15
- SimpleCov::Formatter::HTMLFormatter,
16
- SimpleCov::Formatter::CoberturaFormatter
17
- ]
10
+ require 'simplecov'
11
+ require 'simplecov-cobertura'
12
+ unless SimpleCov.running || ARGV.include?('--no-cov')
13
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new(
14
+ [
15
+ SimpleCov::Formatter::HTMLFormatter,
16
+ SimpleCov::Formatter::CoberturaFormatter
17
+ ]
18
+ )
19
+ SimpleCov.minimum_coverage 80
20
+ SimpleCov.minimum_coverage_by_file 80
18
21
  SimpleCov.start do
19
- enable_coverage :branch
22
+ add_filter 'vendor/'
23
+ add_filter 'target/'
24
+ add_filter 'test/'
25
+ add_filter 'lib/fbe/github_graph.rb'
20
26
  track_files 'lib/**/*.rb'
21
- add_filter '/test/'
22
- add_filter '/vendor/'
27
+ track_files '*.rb'
23
28
  end
24
29
  end
25
30
 
31
+ require 'minitest/reporters'
32
+ Minitest::Reporters.use! [Minitest::Reporters::SpecReporter.new]
33
+
26
34
  require 'minitest/autorun'
35
+ require 'webmock/minitest'
36
+ require_relative '../lib/fbe'
37
+
38
+ # Parent class for all tests.
39
+ class Fbe::Test < Minitest::Test
40
+ end
data/test/test_fbe.rb CHANGED
@@ -10,7 +10,7 @@ require_relative '../lib/fbe'
10
10
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
11
11
  # Copyright:: Copyright (c) 2024-2025 Zerocracy
12
12
  # License:: MIT
13
- class TestFbe < Minitest::Test
13
+ class TestFbe < Fbe::Test
14
14
  def test_simple
15
15
  refute_nil(Fbe::VERSION)
16
16
  end
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.5.1
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-06 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
@@ -219,6 +219,20 @@ dependencies:
219
219
  - - "~>"
220
220
  - !ruby/object:Gem::Version
221
221
  version: '0'
222
+ - !ruby/object:Gem::Dependency
223
+ name: tago
224
+ requirement: !ruby/object:Gem::Requirement
225
+ requirements:
226
+ - - "~>"
227
+ - !ruby/object:Gem::Version
228
+ version: '0'
229
+ type: :runtime
230
+ prerelease: false
231
+ version_requirements: !ruby/object:Gem::Requirement
232
+ requirements:
233
+ - - "~>"
234
+ - !ruby/object:Gem::Version
235
+ version: '0'
222
236
  - !ruby/object:Gem::Dependency
223
237
  name: verbose
224
238
  requirement: !ruby/object:Gem::Requirement
@@ -257,7 +271,6 @@ files:
257
271
  - ".pdd"
258
272
  - ".rubocop.yml"
259
273
  - ".rultor.yml"
260
- - ".simplecov"
261
274
  - ".yamllint.yml"
262
275
  - Gemfile
263
276
  - Gemfile.lock
@@ -292,7 +305,6 @@ files:
292
305
  - lib/fbe/just_one.rb
293
306
  - lib/fbe/middleware.rb
294
307
  - lib/fbe/middleware/formatter.rb
295
- - lib/fbe/middleware/quota.rb
296
308
  - lib/fbe/octo.rb
297
309
  - lib/fbe/overwrite.rb
298
310
  - lib/fbe/pmp.rb
@@ -304,7 +316,6 @@ files:
304
316
  - renovate.json
305
317
  - rules/basic.fe
306
318
  - test/fbe/middleware/test_formatter.rb
307
- - test/fbe/middleware/test_quota.rb
308
319
  - test/fbe/test_award.rb
309
320
  - test/fbe/test_bylaws.rb
310
321
  - test/fbe/test_conclude.rb
data/.simplecov DELETED
@@ -1,24 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- #
4
- # SPDX-FileCopyrightText: Copyright (c) 2024-2025 Zerocracy
5
- # SPDX-License-Identifier: MIT
6
-
7
- if Gem.win_platform?
8
- SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
9
- SimpleCov::Formatter::HTMLFormatter
10
- ]
11
- SimpleCov.start do
12
- add_filter '/test/'
13
- add_filter '/features/'
14
- end
15
- else
16
- SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new(
17
- [SimpleCov::Formatter::HTMLFormatter]
18
- )
19
- SimpleCov.start do
20
- add_filter '/test/'
21
- add_filter '/features/'
22
- minimum_coverage 15
23
- end
24
- end
@@ -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 < Minitest::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