fbe 0.0.1

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.
@@ -0,0 +1,103 @@
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_relative '../fbe'
26
+ require_relative 'unmask_repos'
27
+ require_relative 'octo'
28
+ require_relative 'fb'
29
+
30
+ # Create a conclude code block.
31
+ def Fbe.iterate(fbx = Fbe.fb, loog = $loog, &)
32
+ c = Fbe::Iterate.new(fbx, loog)
33
+ c.instance_eval(&)
34
+ end
35
+
36
+ # Iterate.
37
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
38
+ # Copyright:: Copyright (c) 2024 Zerocracy
39
+ # License:: MIT
40
+ class Fbe::Iterate
41
+ def initialize(fb, loog)
42
+ @fb = fb
43
+ @loog = loog
44
+ @label = nil
45
+ @since = 0
46
+ @query = nil
47
+ @limit = 100
48
+ @quota_aware = false
49
+ end
50
+
51
+ def quota_aware
52
+ @quota_aware = true
53
+ end
54
+
55
+ def limit(limit)
56
+ raise 'Cannot set "limit" to nil' if limit.nil?
57
+ @limit = limit
58
+ end
59
+
60
+ def by(query)
61
+ raise 'Query is already set' unless @query.nil?
62
+ raise 'Cannot set query to nil' if query.nil?
63
+ @query = query
64
+ end
65
+
66
+ def as(label)
67
+ raise 'Label is already set' unless @label.nil?
68
+ raise 'Cannot set "label" to nil' if label.nil?
69
+ @label = label
70
+ end
71
+
72
+ def over(&)
73
+ raise 'Use "as" first' if @label.nil?
74
+ raise 'Use "by" first' if @query.nil?
75
+ seen = {}
76
+ oct = Fbe.octo(loog: @loog)
77
+ repos = Fbe.unmask_repos(loog: @loog)
78
+ loop do
79
+ repos.each do |repo|
80
+ seen[repo] = 0 if seen[repo].nil?
81
+ next if seen[repo] > @limit
82
+ rid = oct.repo_id_by_name(repo)
83
+ before = Fbe.fb.query("(agg (and (eq what '#{@label}') (eq repository #{rid})) (first latest))").one
84
+ Fbe.fb.query("(and (eq what '#{@label}') (eq repository #{rid}))").delete!
85
+ before = before.nil? ? @since : before[0]
86
+ nxt = Fbe.fb.query(@query).one(before:, repository: rid)
87
+ after = nxt.nil? ? @since : yield(rid, nxt)
88
+ raise "Iterator must return an Integer, while #{after.class} returned" unless after.is_a?(Integer)
89
+ f = Fbe.fb.insert
90
+ f.repository = rid
91
+ f.latest = after.nil? ? nxt : after
92
+ f.what = @label
93
+ seen[repo] += 1
94
+ break if oct.off_quota
95
+ end
96
+ break if oct.off_quota
97
+ unless seen.values.any? { |v| v < @limit }
98
+ @loog.debug("Finished scanning #{repos.size} repos: #{seen.map { |k, v| "#{k}:#{v}" }.join(', ')}")
99
+ break
100
+ end
101
+ end
102
+ end
103
+ end
data/lib/fbe/octo.rb ADDED
@@ -0,0 +1,260 @@
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 'loog'
26
+ require 'decoor'
27
+ require 'obk'
28
+ require 'octokit'
29
+ require 'verbose'
30
+ require 'faraday/http_cache'
31
+ require 'faraday/retry'
32
+ require_relative '../fbe'
33
+
34
+ def Fbe.octo(options: $options, global: $global, loog: Loog::NULL)
35
+ raise 'The $global is not set' if global.nil?
36
+ global[:octo] ||= begin
37
+ if options.testing.nil?
38
+ o = Octokit::Client.new
39
+ token = options.token
40
+ loog.debug("The 'token' option is not provided") if token.nil?
41
+ token = ENV.fetch('GITHUB_TOKEN', nil) if token.nil?
42
+ loog.debug("The 'GITHUB_TOKEN' environment variable is not set") if token.nil?
43
+ if token.nil?
44
+ loog.warn('Accessing GitHub API without a token!')
45
+ else
46
+ o = Octokit::Client.new(access_token: token)
47
+ loog.info("Accessing GitHub API with a token (#{token.length} chars)")
48
+ end
49
+ o.auto_paginate = true
50
+ o.connection_options = {
51
+ request: {
52
+ open_timeout: 15,
53
+ timeout: 15
54
+ }
55
+ }
56
+ stack = Faraday::RackBuilder.new do |builder|
57
+ builder.use(Faraday::Retry::Middleware)
58
+ builder.use(Faraday::HttpCache, serializer: Marshal, shared_cache: false)
59
+ builder.use(Octokit::Response::RaiseError)
60
+ builder.adapter(Faraday.default_adapter)
61
+ end
62
+ o.middleware = stack
63
+ o = Verbose.new(o, log: loog)
64
+ else
65
+ loog.debug('The connection to GitHub API is mocked')
66
+ o = Fbe::FakeOctokit.new
67
+ end
68
+ decoor(o, loog:) do
69
+ def off_quota
70
+ left = @origin.rate_limit.remaining
71
+ if left < 5
72
+ @loog.info("To much GitHub API quota consumed already (remaining=#{left}), stopping")
73
+ true
74
+ else
75
+ false
76
+ end
77
+ end
78
+
79
+ def user_name_by_id(id)
80
+ json = @origin.user(id)
81
+ name = json[:login]
82
+ @loog.debug("GitHub user ##{id} has a name: @#{name}")
83
+ name
84
+ end
85
+
86
+ def repo_id_by_name(name)
87
+ json = @origin.repository(name)
88
+ id = json[:id]
89
+ @loog.debug("GitHub repository #{name} has an ID: ##{id}")
90
+ id
91
+ end
92
+
93
+ def repo_name_by_id(id)
94
+ json = @origin.repository(id)
95
+ name = json[:full_name]
96
+ @loog.debug("GitHub repository ##{id} has a name: #{name}")
97
+ name
98
+ end
99
+ end
100
+ end
101
+ end
102
+
103
+ # Fake GitHub client, for tests.
104
+ class Fbe::FakeOctokit
105
+ def random_time
106
+ Time.now - rand(10_000)
107
+ end
108
+
109
+ def name_to_number(name)
110
+ return name unless name.is_a?(String)
111
+ name.chars.map(&:ord).inject(0, :+)
112
+ end
113
+
114
+ def rate_limit
115
+ o = Object.new
116
+ def o.remaining
117
+ 100
118
+ end
119
+ o
120
+ end
121
+
122
+ def repositories(_user = nil)
123
+ [
124
+ {
125
+ name: 'judges',
126
+ full_name: 'yegor256/judges',
127
+ id: 444
128
+ }
129
+ ]
130
+ end
131
+
132
+ def user(name)
133
+ {
134
+ id: 444,
135
+ login: 'yegor256',
136
+ type: name == 29_139_614 ? 'Bot' : 'User'
137
+ }
138
+ end
139
+
140
+ def repository(name)
141
+ {
142
+ id: name_to_number(name),
143
+ full_name: name.is_a?(Integer) ? 'yegor256/test' : name
144
+ }
145
+ end
146
+
147
+ def add_comment(_repo, _issue, _text)
148
+ 42
149
+ end
150
+
151
+ def search_issues(_query, _options = {})
152
+ {
153
+ items: [
154
+ {
155
+ number: 42,
156
+ labels: [
157
+ {
158
+ name: 'bug'
159
+ }
160
+ ]
161
+ }
162
+ ]
163
+ }
164
+ end
165
+
166
+ def issue_timeline(_repo, _issue, _options = {})
167
+ [
168
+ {
169
+ actor: {
170
+ id: 888,
171
+ login: 'torvalds'
172
+ },
173
+ repository: {
174
+ id: name_to_number('yegor256/judges'),
175
+ full_name: 'yegor256/judges'
176
+ },
177
+ event: 'renamed',
178
+ rename: {
179
+ from: 'before',
180
+ to: 'after'
181
+ },
182
+ created_at: random_time
183
+ },
184
+ {
185
+ actor: {
186
+ id: 888,
187
+ login: 'torvalds'
188
+ },
189
+ repository: {
190
+ id: name_to_number('yegor256/judges'),
191
+ full_name: 'yegor256/judges'
192
+ },
193
+ event: 'labeled',
194
+ label: {
195
+ name: 'bug'
196
+ },
197
+ created_at: random_time
198
+ }
199
+ ]
200
+ end
201
+
202
+ def repository_events(repo, _options = {})
203
+ [
204
+ {
205
+ id: '123',
206
+ repo: {
207
+ id: name_to_number(repo),
208
+ name: repo
209
+ },
210
+ type: 'PushEvent',
211
+ payload: {
212
+ push_id: 42
213
+ },
214
+ actor: {
215
+ id: 888,
216
+ login: 'torvalds'
217
+ },
218
+ created_at: random_time
219
+ },
220
+ {
221
+ id: '124',
222
+ repo: {
223
+ id: name_to_number(repo),
224
+ name: repo
225
+ },
226
+ type: 'IssuesEvent',
227
+ payload: {
228
+ action: 'closed',
229
+ issue: {
230
+ number: 42
231
+ }
232
+ },
233
+ actor: {
234
+ id: 888,
235
+ login: 'torvalds'
236
+ },
237
+ created_at: random_time
238
+ },
239
+ {
240
+ id: '125',
241
+ repo: {
242
+ id: name_to_number(repo),
243
+ name: repo
244
+ },
245
+ type: 'IssuesEvent',
246
+ payload: {
247
+ action: 'opened',
248
+ issue: {
249
+ number: 42
250
+ }
251
+ },
252
+ actor: {
253
+ id: 888,
254
+ login: 'torvalds'
255
+ },
256
+ created_at: random_time
257
+ }
258
+ ]
259
+ end
260
+ end
@@ -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_relative 'octo'
26
+
27
+ # Unmask.
28
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
29
+ # Copyright:: Copyright (c) 2024 Zerocracy
30
+ # License:: MIT
31
+ module Fbe
32
+ def self.mask_to_regex(mask)
33
+ org, repo = mask.split('/')
34
+ raise "Org '#{org}' can't have an asterisk" if org.include?('*')
35
+ Regexp.compile("#{org}/#{repo.gsub('*', '.*')}")
36
+ end
37
+
38
+ def self.unmask_repos(options: $options, global: $global, loog: $loog)
39
+ repos = []
40
+ masks = (options.repositories || '').split(',')
41
+ masks.reject { |m| m.start_with?('-') }.each do |mask|
42
+ unless mask.include?('*')
43
+ repos << mask
44
+ next
45
+ end
46
+ re = Fbe.mask_to_regex(mask)
47
+ Fbe.octo(loog:, global:, options:).repositories(mask.split('/')[0]).each do |r|
48
+ repos << r[:full_name] if re.match?(r[:full_name])
49
+ end
50
+ end
51
+ masks.select { |m| m.start_with?('-') }.each do |mask|
52
+ re = Fbe.mask_to_regex(mask[1..])
53
+ repos.reject! { |r| re.match?(r) }
54
+ end
55
+ loog.debug("Scanning #{repos.size} repositories: #{repos.join(', ')}...")
56
+ repos
57
+ end
58
+ end
data/lib/fbe.rb ADDED
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2024 Zerocracy
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ # The module.
24
+ #
25
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
26
+ # Copyright:: Copyright (c) 2024 Zerocracy
27
+ # License:: MIT
28
+ module Fbe
29
+ # Current version of the gem (changed by .rultor.yml on every release)
30
+ VERSION = '0.0.1'
31
+ end
data/renovate.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3
+ "extends": [
4
+ "config:base"
5
+ ]
6
+ }
data/rules/basic.fe ADDED
@@ -0,0 +1,158 @@
1
+ # MIT License
2
+ #
3
+ # Copyright (c) 2024 Zerocracy
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ (undef explain)
24
+ (defn explain '
25
+ r = @operands[0].evaluate(fact, maps);
26
+ if !r && !$loog.nil?
27
+ $loog.error(\'This rule failed: \' + self.to_s)
28
+ end
29
+ return r
30
+ ')
31
+
32
+ (explain (when
33
+ (exists what)
34
+ (or
35
+ (eq what 'events-were-scanned')
36
+ (eq what 'labels-were-scanned')
37
+ (eq what 'bug-was-accepted')
38
+ (eq what 'bug-was-resolved')
39
+ (eq what 'comment-was-posted')
40
+ (eq what 'git-was-pushed')
41
+ (eq what 'events-were-scanned')
42
+ (eq what 'issue-was-closed')
43
+ (eq what 'issue-was-opened')
44
+ (eq what 'issue-was-assigned')
45
+ (eq what 'label-was-attached')
46
+ (eq what 'release-published')
47
+ (eq what 'reward-for-bug-reported')
48
+ (eq what 'reward-for-resolved-bug')
49
+ (eq what 'tag-was-created'))))
50
+
51
+ (explain (when
52
+ (exists what)
53
+ (matches what "^[a-z]+(-[a-z]+)*$")))
54
+
55
+ (explain (when
56
+ (exists details)
57
+ (and
58
+ (not (matches details " "))
59
+ (not (matches details "^.{,120}$"))
60
+ (not (matches details "[^.]$")))))
61
+
62
+ (explain (when
63
+ (exists _id)
64
+ (eq "Integer" (type _id))))
65
+ (explain (when
66
+ (exists _time)
67
+ (eq "Time" (type _time))))
68
+ (explain (when
69
+ (exists _version)
70
+ (eq "String" (type _version))))
71
+ (explain (when
72
+ (exists issue)
73
+ (and
74
+ (eq "Integer" (type issue))
75
+ (gt issue 0))))
76
+ (explain (when
77
+ (exists repository)
78
+ (eq "Integer" (type repository))))
79
+ (explain (when
80
+ (exists who)
81
+ (eq "Integer" (type who))))
82
+ (explain (when
83
+ (exists award)
84
+ (eq "Integer" (type award))))
85
+
86
+ (explain (when
87
+ (exists when)
88
+ (eq "Time" (type when))))
89
+
90
+ (explain (when
91
+ (exists issue)
92
+ (exists repository)))
93
+
94
+ (explain (when
95
+ (exists award)
96
+ (and
97
+ (exists when)
98
+ (exists who)
99
+ (exists reason))))
100
+
101
+ (explain (when
102
+ (eq what 'events-were-scanned')
103
+ (and
104
+ (exists repository)
105
+ (exists latest)
106
+ (eq "Integer" (type latest)))))
107
+
108
+ (explain (when
109
+ (eq what 'label-was-attached')
110
+ (and
111
+ (exists issue)
112
+ (exists label)
113
+ (eq "String" (type label)))))
114
+
115
+ (explain (when
116
+ (eq what 'issue-was-opened')
117
+ (and
118
+ (exists issue)
119
+ (exists when)
120
+ (exists who))))
121
+
122
+ (explain (when
123
+ (eq what 'issue-was-closed')
124
+ (and
125
+ (exists issue)
126
+ (exists when)
127
+ (exists who))))
128
+
129
+ (explain (when
130
+ (eq what 'bug-was-resolved')
131
+ (and
132
+ (exists cause)
133
+ (exists when)
134
+ (exists issue)
135
+ (exists details)
136
+ (exists who))))
137
+
138
+ (explain (when
139
+ (eq what 'bug-was-accepted')
140
+ (and
141
+ (exists cause)
142
+ (exists when)
143
+ (exists issue)
144
+ (exists details)
145
+ (exists reporter)
146
+ (eq "Integer" (type reporter))
147
+ (exists who))))
148
+
149
+ (explain (when
150
+ (eq what 'bug-report-was-rewarded')
151
+ (and
152
+ (exists cause)
153
+ (exists award)
154
+ (eq "Integer" (type award))
155
+ (exists when)
156
+ (exists issue)
157
+ (exists repository))))
158
+
@@ -0,0 +1,89 @@
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 'loog'
27
+ require 'factbase'
28
+ require 'factbase/syntax'
29
+ require 'judges/options'
30
+ require_relative '../../lib/fbe/conclude'
31
+ require_relative '../../lib/fbe/fb'
32
+
33
+ # Test.
34
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
35
+ # Copyright:: Copyright (c) 2024 Zerocracy
36
+ # License:: MIT
37
+ class TestConclude < Minitest::Test
38
+ def test_draw
39
+ fb = Factbase.new
40
+ fb.insert.foo = 1
41
+ fb.insert.bar = 2
42
+ Fbe.conclude(fb, 'judge-one', Loog::NULL) do
43
+ on '(exists foo)'
44
+ draw do |n, prev|
45
+ n.sum = prev.foo + 1
46
+ 'something funny'
47
+ end
48
+ end
49
+ f = fb.query('(exists sum)').each.to_a[0]
50
+ assert_equal(2, f.sum)
51
+ assert_equal('judge-one', f.what)
52
+ assert_equal('something funny', f.details)
53
+ end
54
+
55
+ def test_maybe
56
+ $fb = Factbase.new
57
+ $options = Judges::Options.new
58
+ $loog = Loog::NULL
59
+ Fbe.fb.insert.foo = 1
60
+ Fbe.conclude(Fbe.fb, 'issue-was-opened', Loog::NULL) do
61
+ on '(exists foo)'
62
+ maybe do |n, prev|
63
+ n.repository = 111
64
+ n.issue = prev.foo
65
+ n.who = 777
66
+ n.when = Time.now
67
+ "it's a test." * 20
68
+ end
69
+ end
70
+ f = Fbe.fb.query('(exists issue)').each.to_a[0]
71
+ assert_equal(1, f.issue)
72
+ assert(f._id.positive?)
73
+ end
74
+
75
+ def test_consider
76
+ $fb = Factbase.new
77
+ $options = Judges::Options.new
78
+ $loog = Loog::NULL
79
+ Fbe.fb.insert.foo = 1
80
+ Fbe.conclude(Fbe.fb, 'issue-was-closed', Loog::NULL) do
81
+ on '(exists foo)'
82
+ consider do |_prev|
83
+ Fbe.fb.insert.bar = 42
84
+ end
85
+ end
86
+ f = Fbe.fb.query('(exists bar)').each.to_a[0]
87
+ assert_equal(42, f.bar)
88
+ end
89
+ end