fbe 0.17.0 → 0.18.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 +4 -4
- data/Gemfile.lock +5 -0
- data/fbe.gemspec +1 -0
- data/lib/fbe/middleware/sqlite_store.rb +83 -0
- data/lib/fbe/octo.rb +11 -1
- data/lib/fbe.rb +1 -1
- data/test/fbe/middleware/test_sqlite_store.rb +35 -0
- data/test/fbe/test_fb.rb +22 -0
- data/test/fbe/test_octo.rb +24 -0
- metadata +17 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4a99af1e0cf0824c00460e0166b3b9882c40b49421989e94c5abcda5d1766042
|
4
|
+
data.tar.gz: e7963ae2eb4bdb52745a10dc5f4d240abf768549f1461098c93e7dc81986936a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0f90f11a2f21822ab37f5b9300ee1dd35858f9ded52baed36404af1bc27d1ebf9880e720a08b0caff73e932fefad80716bddcdafb87f0e8b7c4c5b2f84014e6c
|
7
|
+
data.tar.gz: 01612e41f4b1d8432b55dff2a4ce3b77af9686a9f9b6b1e3c9ff099f10ec447ee1b7594bf9808297d3a799656f92909a2112f7234d6a603199bd5c2c154fe6a5
|
data/Gemfile.lock
CHANGED
@@ -17,6 +17,7 @@ PATH
|
|
17
17
|
obk (> 0)
|
18
18
|
octokit (~> 10.0)
|
19
19
|
others (> 0)
|
20
|
+
sqlite3 (~> 2.6)
|
20
21
|
tago (> 0)
|
21
22
|
verbose (> 0)
|
22
23
|
|
@@ -217,6 +218,10 @@ GEM
|
|
217
218
|
simplecov (~> 0.19)
|
218
219
|
simplecov-html (0.13.1)
|
219
220
|
simplecov_json_formatter (0.1.4)
|
221
|
+
sqlite3 (2.6.0-arm64-darwin)
|
222
|
+
sqlite3 (2.6.0-x64-mingw-ucrt)
|
223
|
+
sqlite3 (2.6.0-x86_64-darwin)
|
224
|
+
sqlite3 (2.6.0-x86_64-linux-gnu)
|
220
225
|
strscan (3.1.5)
|
221
226
|
tago (0.1.0)
|
222
227
|
timeout (0.4.3)
|
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', '~>10.0'
|
39
39
|
s.add_dependency 'others', '>0'
|
40
|
+
s.add_dependency 'sqlite3', '~> 2.6'
|
40
41
|
s.add_dependency 'tago', '>0'
|
41
42
|
s.add_dependency 'verbose', '>0'
|
42
43
|
s.metadata['rubygems_mfa_required'] = 'true'
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Zerocracy
|
4
|
+
# SPDX-License-Identifier: MIT
|
5
|
+
|
6
|
+
require 'json'
|
7
|
+
require 'sqlite3'
|
8
|
+
require_relative '../../fbe'
|
9
|
+
require_relative '../../fbe/middleware'
|
10
|
+
|
11
|
+
# Persisted SQLite store for Faraday::HttpCache
|
12
|
+
#
|
13
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
14
|
+
# Copyright:: Copyright (c) 2024-2025 Zerocracy
|
15
|
+
# License:: MIT
|
16
|
+
class Fbe::Middleware::SqliteStore
|
17
|
+
def initialize(path)
|
18
|
+
raise ArgumentError, 'Database path cannot be nil or empty' if path.nil? || path.empty?
|
19
|
+
dir = File.dirname(path)
|
20
|
+
raise ArgumentError, "Directory #{dir} does not exist" unless File.directory?(dir)
|
21
|
+
@path = path
|
22
|
+
open
|
23
|
+
prepare
|
24
|
+
at_exit { close }
|
25
|
+
end
|
26
|
+
|
27
|
+
def read(key)
|
28
|
+
value = perform { _1.execute('SELECT value FROM cache WHERE key = ? LIMIT 1', [key]) }.dig(0, 0)
|
29
|
+
JSON.parse(value) if value
|
30
|
+
end
|
31
|
+
|
32
|
+
def delete(key)
|
33
|
+
perform { _1.execute('DELETE FROM cache WHERE key = ?', [key]) }
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
|
37
|
+
def write(key, value)
|
38
|
+
value = JSON.dump(value)
|
39
|
+
perform do |tdb|
|
40
|
+
tdb.execute(<<~SQL, [key, value])
|
41
|
+
INSERT INTO cache(key, value) VALUES(?1, ?2)
|
42
|
+
ON CONFLICT(key) DO UPDATE SET value = ?2
|
43
|
+
SQL
|
44
|
+
end
|
45
|
+
nil
|
46
|
+
end
|
47
|
+
|
48
|
+
def open
|
49
|
+
return if @db
|
50
|
+
@db = SQLite3::Database.new(@path)
|
51
|
+
end
|
52
|
+
|
53
|
+
def prepare
|
54
|
+
perform do |tdb|
|
55
|
+
tdb.execute 'CREATE TABLE IF NOT EXISTS cache(key TEXT UNIQUE NOT NULL, value TEXT);'
|
56
|
+
tdb.execute 'CREATE INDEX IF NOT EXISTS key_idx ON cache(key);'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def close
|
61
|
+
return if !@db || @db.closed?
|
62
|
+
@db.close
|
63
|
+
@db = nil
|
64
|
+
end
|
65
|
+
|
66
|
+
def clear
|
67
|
+
perform { _1.execute 'DELETE FROM cache;' }
|
68
|
+
end
|
69
|
+
|
70
|
+
def drop
|
71
|
+
perform { _1.execute 'DROP TABLE IF EXISTS cache;' }
|
72
|
+
end
|
73
|
+
|
74
|
+
def all
|
75
|
+
perform { _1.execute('SELECT key, value FROM cache') }
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def perform(&)
|
81
|
+
@db.transaction(&)
|
82
|
+
end
|
83
|
+
end
|
data/lib/fbe/octo.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 'json'
|
6
7
|
require 'decoor'
|
7
8
|
require 'faraday/http_cache'
|
8
9
|
require 'faraday/retry'
|
@@ -15,6 +16,7 @@ require_relative '../fbe'
|
|
15
16
|
require_relative 'middleware'
|
16
17
|
require_relative 'middleware/formatter'
|
17
18
|
require_relative 'middleware/trace'
|
19
|
+
require_relative 'middleware/sqlite_store'
|
18
20
|
|
19
21
|
# Makes a call to the GitHub API.
|
20
22
|
#
|
@@ -78,7 +80,15 @@ def Fbe.octo(options: $options, global: $global, loog: $loog)
|
|
78
80
|
methods: [:get],
|
79
81
|
backoff_factor: 2
|
80
82
|
)
|
81
|
-
|
83
|
+
serializer = Marshal
|
84
|
+
if options.sqlite_cache
|
85
|
+
store = Fbe::Middleware::SqliteStore.new(options.sqlite_cache)
|
86
|
+
serializer = JSON
|
87
|
+
end
|
88
|
+
builder.use(
|
89
|
+
Faraday::HttpCache,
|
90
|
+
store: store, serializer: serializer, shared_cache: false, logger: Loog::NULL
|
91
|
+
)
|
82
92
|
builder.use(Octokit::Response::RaiseError)
|
83
93
|
builder.use(Faraday::Response::Logger, loog, formatter: Fbe::Middleware::Formatter)
|
84
94
|
builder.use(Fbe::Middleware::Trace, trace)
|
data/lib/fbe.rb
CHANGED
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Zerocracy
|
4
|
+
# SPDX-License-Identifier: MIT
|
5
|
+
|
6
|
+
require_relative '../../test__helper'
|
7
|
+
require_relative '../../../lib/fbe/middleware'
|
8
|
+
require_relative '../../../lib/fbe/middleware/sqlite_store'
|
9
|
+
|
10
|
+
# Test.
|
11
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
12
|
+
# Copyright:: Copyright (c) 2024-2025 Zerocracy
|
13
|
+
# License:: MIT
|
14
|
+
class SqliteStoreTest < Fbe::Test
|
15
|
+
def test_sqlite_store
|
16
|
+
Dir.mktmpdir do |dir|
|
17
|
+
store = Fbe::Middleware::SqliteStore.new(File.expand_path('test.db', dir))
|
18
|
+
assert_nil(store.read('my_key'))
|
19
|
+
assert_nil(store.delete('my_key'))
|
20
|
+
assert_nil(store.write('my_key', 'some value'))
|
21
|
+
assert_equal('some value', store.read('my_key'))
|
22
|
+
assert_nil(store.write('my_key', 'some value 2'))
|
23
|
+
assert_equal('some value 2', store.read('my_key'))
|
24
|
+
assert_nil(store.delete('my_key'))
|
25
|
+
assert_nil(store.read('my_key'))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_sqlite_store_empty_all
|
30
|
+
Dir.mktmpdir do |dir|
|
31
|
+
store = Fbe::Middleware::SqliteStore.new(File.expand_path('test.db', dir))
|
32
|
+
assert_empty(store.all)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/test/fbe/test_fb.rb
CHANGED
@@ -27,6 +27,28 @@ class TestFb < Fbe::Test
|
|
27
27
|
assert_includes(stdout, 'Inserted new fact #1', stdout)
|
28
28
|
end
|
29
29
|
|
30
|
+
def test_defends_against_improper_facts
|
31
|
+
$fb = Factbase.new
|
32
|
+
$global = {}
|
33
|
+
$options = Judges::Options.new
|
34
|
+
$loog = Loog::Buffer.new
|
35
|
+
assert_raises(StandardError, 'issue without repository') do
|
36
|
+
Fbe.fb.txn do |fbt|
|
37
|
+
f = fbt.insert
|
38
|
+
f.what = 'issue-was-opened'
|
39
|
+
f.issue = 42
|
40
|
+
f.where = 'github'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
assert_raises(StandardError, 'repository without where') do
|
44
|
+
Fbe.fb.txn do |fbt|
|
45
|
+
f = fbt.insert
|
46
|
+
f.what = 'issue-was-opened'
|
47
|
+
f.repository = 44
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
30
52
|
def test_increment_id_in_transaction
|
31
53
|
$fb = Factbase.new
|
32
54
|
$global = {}
|
data/test/fbe/test_octo.rb
CHANGED
@@ -366,4 +366,28 @@ class TestOcto < Fbe::Test
|
|
366
366
|
second_output = second_loog.to_s
|
367
367
|
assert_includes second_output, 'GitHub API trace is empty'
|
368
368
|
end
|
369
|
+
|
370
|
+
def test_sqlite_store
|
371
|
+
WebMock.disable_net_connect!
|
372
|
+
Dir.mktmpdir do |dir|
|
373
|
+
global = {}
|
374
|
+
sqlite_cache = File.expand_path('test.db', dir)
|
375
|
+
o = Fbe.octo(loog: Loog::NULL, global:, options: Judges::Options.new({ 'sqlite_cache' => sqlite_cache }))
|
376
|
+
stub = stub_request(:get, 'https://api.github.com/user/42').to_return(
|
377
|
+
status: 200,
|
378
|
+
body: { login: 'user1' }.to_json,
|
379
|
+
headers: {
|
380
|
+
'Content-Type' => 'application/json',
|
381
|
+
'Cache-Control' => 'public, max-age=60, s-maxage=60',
|
382
|
+
'Etag' => 'W/"2ff9dd4c3153f006830b2b8b721f6a4bb400a1eb81a2e1fa0a3b846ad349b9ec"',
|
383
|
+
'Last-Modified' => 'Wed, 01 May 2025 20:00:00 GMT'
|
384
|
+
}
|
385
|
+
)
|
386
|
+
assert_equal('user1', o.user_name_by_id(42))
|
387
|
+
WebMock.remove_request_stub(stub)
|
388
|
+
global = {}
|
389
|
+
o = Fbe.octo(loog: Loog::NULL, global:, options: Judges::Options.new({ 'sqlite_cache' => sqlite_cache }))
|
390
|
+
assert_equal('user1', o.user_name_by_id(42))
|
391
|
+
end
|
392
|
+
end
|
369
393
|
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.
|
4
|
+
version: 0.18.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yegor Bugayenko
|
@@ -219,6 +219,20 @@ dependencies:
|
|
219
219
|
- - ">"
|
220
220
|
- !ruby/object:Gem::Version
|
221
221
|
version: '0'
|
222
|
+
- !ruby/object:Gem::Dependency
|
223
|
+
name: sqlite3
|
224
|
+
requirement: !ruby/object:Gem::Requirement
|
225
|
+
requirements:
|
226
|
+
- - "~>"
|
227
|
+
- !ruby/object:Gem::Version
|
228
|
+
version: '2.6'
|
229
|
+
type: :runtime
|
230
|
+
prerelease: false
|
231
|
+
version_requirements: !ruby/object:Gem::Requirement
|
232
|
+
requirements:
|
233
|
+
- - "~>"
|
234
|
+
- !ruby/object:Gem::Version
|
235
|
+
version: '2.6'
|
222
236
|
- !ruby/object:Gem::Dependency
|
223
237
|
name: tago
|
224
238
|
requirement: !ruby/object:Gem::Requirement
|
@@ -307,6 +321,7 @@ files:
|
|
307
321
|
- lib/fbe/just_one.rb
|
308
322
|
- lib/fbe/middleware.rb
|
309
323
|
- lib/fbe/middleware/formatter.rb
|
324
|
+
- lib/fbe/middleware/sqlite_store.rb
|
310
325
|
- lib/fbe/middleware/trace.rb
|
311
326
|
- lib/fbe/octo.rb
|
312
327
|
- lib/fbe/overwrite.rb
|
@@ -319,6 +334,7 @@ files:
|
|
319
334
|
- renovate.json
|
320
335
|
- rules/basic.fe
|
321
336
|
- test/fbe/middleware/test_formatter.rb
|
337
|
+
- test/fbe/middleware/test_sqlite_store.rb
|
322
338
|
- test/fbe/middleware/test_trace.rb
|
323
339
|
- test/fbe/test_award.rb
|
324
340
|
- test/fbe/test_bylaws.rb
|