lazylead 0.4.3 → 0.5.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/.docs/accuracy.md +2 -2
- data/.docs/duedate_expired.md +3 -3
- data/.docs/propagate_down.md +3 -3
- data/.gitattributes +1 -0
- data/Rakefile +2 -0
- data/bin/lazylead +1 -1
- data/lazylead.gemspec +2 -2
- data/lib/lazylead/exchange.rb +15 -8
- data/lib/lazylead/model.rb +35 -1
- data/lib/lazylead/opts.rb +12 -0
- data/lib/lazylead/schedule.rb +16 -15
- data/lib/lazylead/system/jira.rb +39 -0
- data/lib/lazylead/task/accuracy/accuracy.rb +4 -8
- data/lib/lazylead/task/accuracy/affected_build.rb +2 -6
- data/lib/lazylead/task/accuracy/attachment.rb +44 -0
- data/lib/lazylead/task/accuracy/environment.rb +39 -0
- data/lib/lazylead/task/accuracy/logs.rb +40 -0
- data/lib/lazylead/task/accuracy/records.rb +45 -0
- data/lib/lazylead/task/accuracy/requirement.rb +9 -0
- data/lib/lazylead/task/accuracy/servers.rb +50 -0
- data/lib/lazylead/task/accuracy/stacktrace.rb +63 -0
- data/lib/lazylead/task/accuracy/testcase.rb +75 -0
- data/lib/lazylead/task/accuracy/wiki.rb +41 -0
- data/lib/lazylead/task/echo.rb +18 -0
- data/lib/lazylead/task/fix_version.rb +9 -2
- data/lib/lazylead/task/touch.rb +23 -8
- data/lib/lazylead/version.rb +1 -1
- data/lib/messages/svn_log.erb +117 -0
- data/license.txt +1 -1
- data/readme.md +5 -5
- data/test/lazylead/cli/app_test.rb +11 -11
- data/test/lazylead/system/jira_test.rb +30 -0
- data/test/lazylead/task/accuracy/accuracy_test.rb +1 -1
- data/test/lazylead/task/accuracy/affected_build_test.rb +2 -2
- data/test/lazylead/task/accuracy/attachment_test.rb +50 -0
- data/test/lazylead/task/accuracy/environment_test.rb +42 -0
- data/test/lazylead/task/accuracy/logs_test.rb +78 -0
- data/test/lazylead/task/accuracy/records_test.rb +60 -0
- data/test/lazylead/task/accuracy/servers_test.rb +66 -0
- data/test/lazylead/task/accuracy/stacktrace_test.rb +113 -0
- data/test/lazylead/task/accuracy/testcase_test.rb +205 -0
- data/test/lazylead/task/accuracy/wiki_test.rb +40 -0
- data/test/lazylead/task/touch_test.rb +28 -1
- data/test/test.rb +16 -0
- data/upgrades/sqlite/001-install-main-lazylead-tables.sql +1 -5
- data/upgrades/sqlite/999.testdata.sql +12 -17
- metadata +28 -4
- data/.travis.yml +0 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a8358ec8da9d97621f9c5ec28ddfa3114699f260af8ae4fd9632a998263f795e
|
4
|
+
data.tar.gz: 4a11f6cbd5cffbc91a2b40a5b7fb6c82d608301d16ebba1d8b2155a256101f48
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 31259a7b7305b519f610e68dbbb7649fee65257415aae4a0bfe1a77bdd88f62662279a4689bb18872d37eba4d8c0b6537ddf5f1a1c415762085e507fb39d05ae
|
7
|
+
data.tar.gz: 2c6bc24efc4696496c8a0c58c697af93377bc7c6d216141138ce8d18f3606104e7a945c715d3657ebc97ede3f97db586da3a6fe57c01f826eb86c61f024f91b7
|
data/.docs/accuracy.md
CHANGED
@@ -66,7 +66,7 @@ For simplicity, we are using [docker-compose](https://docs.docker.com/compose/):
|
|
66
66
|
values (1,'{"type":"Lazylead::Jira", "username":"${jira_user}", "password":"${jira_password}", "site":"${jira_url}", "context_path":""}');
|
67
67
|
insert into tasks (name, cron, enabled, id, system, team_id, action, properties)
|
68
68
|
values ('Post ticket score and accuracy to the tickets',
|
69
|
-
'0 8 * * 1-5',
|
69
|
+
'cron:0 8 * * 1-5',
|
70
70
|
'true',
|
71
71
|
1, 1, 1,
|
72
72
|
'Lazylead::Task::Accuracy',
|
@@ -82,7 +82,7 @@ For simplicity, we are using [docker-compose](https://docs.docker.com/compose/):
|
|
82
82
|
}
|
83
83
|
');
|
84
84
|
```
|
85
|
-
Yes, for task scheduling we are using [cron](https://crontab.guru).
|
85
|
+
Yes, for task scheduling we are using [cron](https://crontab.guru) here, but you may use other scheduling types from [rufus-scheduler](https://github.com/jmettraux/rufus-scheduler).
|
86
86
|
|
87
87
|
4. Once you changed `./ll.db`, please restart the container using `docker-compose -f .github/tasks.yml restart`
|
88
88
|
```bash
|
data/.docs/duedate_expired.md
CHANGED
@@ -68,16 +68,16 @@ For simplicity, we are using [docker-compose](https://docs.docker.com/compose/):
|
|
68
68
|
values (1, 'Dream team with lazylead', '{}');
|
69
69
|
insert into systems(id, properties)
|
70
70
|
values (1,'{"type":"Lazylead::Jira", "username":"${jira_user}", "password":"${jira_password}", "site":"${jira_url}", "context_path":""}');
|
71
|
-
insert into tasks (name,
|
71
|
+
insert into tasks (name, schedule, enabled, id, system, team_id, action, properties)
|
72
72
|
values ('Expired due dates',
|
73
|
-
'0 8 * * 1-5',
|
73
|
+
'cron:0 8 * * 1-5',
|
74
74
|
'true',
|
75
75
|
1, 1, 1,
|
76
76
|
'Lazylead::Task::AssigneeAlert',
|
77
77
|
'{"sql":"filter=222", "cc":"<youremail.com>", "subject":"[LL] Expired due dates", "template":"lib/messages/due_date_expired.erb", "postman":"Lazylead::Exchange"}');
|
78
78
|
|
79
79
|
```
|
80
|
-
Yes, for task scheduling we are using [cron](https://crontab.guru).
|
80
|
+
Yes, for task scheduling we are using [cron](https://crontab.guru) here, but you may use other scheduling types from [rufus-scheduler](https://github.com/jmettraux/rufus-scheduler).
|
81
81
|
|
82
82
|
4. Once you changed `./ll.db`, please restart the container using `docker-compose -f .github/tasks.yml restart`
|
83
83
|
```bash
|
data/.docs/propagate_down.md
CHANGED
@@ -58,16 +58,16 @@ For simplicity, we are using [docker-compose](https://docs.docker.com/compose/):
|
|
58
58
|
values (1, 'Dream team with lazylead', '{}');
|
59
59
|
insert into systems(id, properties)
|
60
60
|
values (1,'{"type":"Lazylead::Jira", "username":"${jira_user}", "password":"${jira_password}", "site":"${jira_url}", "context_path":""}');
|
61
|
-
insert into tasks (name,
|
61
|
+
insert into tasks (name, schedule, enabled, id, system, team_id, action, properties)
|
62
62
|
values ('Propagate customfield_1 (External ID) to sub-tasks',
|
63
|
-
'0 8 * * 1-5',
|
63
|
+
'cron:0 8 * * 1-5',
|
64
64
|
'true',
|
65
65
|
1, 1, 1,
|
66
66
|
'Lazylead::Task::PropagateDown',
|
67
67
|
'{"jql":"filter=222", "propagate":"customfield_1"}');
|
68
68
|
|
69
69
|
```
|
70
|
-
Yes, for task scheduling we are using [cron](https://crontab.guru).
|
70
|
+
Yes, for task scheduling we are using [cron](https://crontab.guru) here, but you may use other scheduling types from [rufus-scheduler](https://github.com/jmettraux/rufus-scheduler).
|
71
71
|
|
72
72
|
4. Once you changed `./ll.db`, please restart the container using `docker-compose -f .github/tasks.yml restart`
|
73
73
|
```bash
|
data/.gitattributes
CHANGED
data/Rakefile
CHANGED
@@ -127,4 +127,6 @@ task :docker do
|
|
127
127
|
system "docker-compose -f .docker/docker-compose.yml build "\
|
128
128
|
" --build-arg release_tags='latest 1.0'"\
|
129
129
|
" --build-arg version=1.0"
|
130
|
+
system "docker-compose -f .docker/docker-compose.yml rm --force -s lazylead"
|
131
|
+
system "docker-compose -f .docker/docker-compose.yml up"
|
130
132
|
end
|
data/bin/lazylead
CHANGED
@@ -82,7 +82,7 @@ log.debug("Memory footprint at start is #{Lazylead::Allocated.new}")
|
|
82
82
|
cmd = lambda do
|
83
83
|
Lazylead::CLI::App.new(
|
84
84
|
log,
|
85
|
-
Lazylead::Schedule.new(log),
|
85
|
+
Lazylead::Schedule.new(log: log),
|
86
86
|
Lazylead::Smtp.new(
|
87
87
|
log, Lazylead::Salt.new("smtp_salt"),
|
88
88
|
smtp_host: ENV["smtp_host"],
|
data/lazylead.gemspec
CHANGED
@@ -32,7 +32,7 @@ Gem::Specification.new do |s|
|
|
32
32
|
s.rubygems_version = "2.2"
|
33
33
|
s.required_ruby_version = ">=2.6.5"
|
34
34
|
s.name = "lazylead"
|
35
|
-
s.version = "0.
|
35
|
+
s.version = "0.5.0"
|
36
36
|
s.license = "MIT"
|
37
37
|
s.summary = "Eliminate the annoying work within bug-trackers."
|
38
38
|
s.description = "Ticketing systems (Github, Jira, etc.) are strongly
|
@@ -45,7 +45,7 @@ tasks instead of solving technical problems."
|
|
45
45
|
s.authors = ["Yurii Dubinka"]
|
46
46
|
s.email = "yurii.dubinka@gmail.com"
|
47
47
|
s.homepage = "http://github.com/dgroup/lazylead"
|
48
|
-
s.post_install_message = "Thanks for installing Lazylead v0.
|
48
|
+
s.post_install_message = "Thanks for installing Lazylead v0.5.0!
|
49
49
|
Read our blog posts: https://lazylead.org
|
50
50
|
Stay in touch with the community in Telegram: https://t.me/lazylead
|
51
51
|
Follow us on Twitter: https://twitter.com/lazylead
|
data/lib/lazylead/exchange.rb
CHANGED
@@ -54,19 +54,26 @@ module Lazylead
|
|
54
54
|
def send(opts)
|
55
55
|
to = opts["to"] || opts[:to]
|
56
56
|
to = [to] unless to.is_a? Array
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
to_recipients: to
|
63
|
-
}
|
57
|
+
if to.reject { |e| e.nil? || e.blank? }.empty?
|
58
|
+
@log.warn "Email can't be sent to '#{to}, more: '#{opts}'"
|
59
|
+
return
|
60
|
+
end
|
61
|
+
msg = make_msg(to, opts)
|
64
62
|
msg.update(cc_recipients: opts["cc"]) if opts.key? "cc"
|
65
63
|
add_attachments(msg, opts)
|
66
64
|
cli.send_message msg
|
67
65
|
close_attachments msg
|
68
66
|
@log.debug "Email was generated from #{opts} and send by #{__FILE__}. " \
|
69
|
-
"Here is the body: #{
|
67
|
+
"Here is the body: '#{msg[:body]}'"
|
68
|
+
end
|
69
|
+
|
70
|
+
def make_msg(to, opts)
|
71
|
+
{
|
72
|
+
subject: opts["subject"],
|
73
|
+
body: make_body(opts),
|
74
|
+
body_type: "HTML",
|
75
|
+
to_recipients: to
|
76
|
+
}
|
70
77
|
end
|
71
78
|
|
72
79
|
def add_attachments(msg, opts)
|
data/lib/lazylead/model.rb
CHANGED
@@ -94,6 +94,7 @@ module Lazylead
|
|
94
94
|
belongs_to :team, foreign_key: "team_id"
|
95
95
|
belongs_to :system, foreign_key: "system"
|
96
96
|
|
97
|
+
# Execute task
|
97
98
|
def exec
|
98
99
|
sys = system.connect
|
99
100
|
opts = props
|
@@ -101,6 +102,25 @@ module Lazylead
|
|
101
102
|
action.constantize.new.run(sys, postman, opts)
|
102
103
|
end
|
103
104
|
|
105
|
+
# Scheduling type.
|
106
|
+
# Current implementation is based on 'rufus-scheduler' gem and supports
|
107
|
+
# the following types: 'cron', 'interval', 'in', 'at', 'every'
|
108
|
+
def type
|
109
|
+
trigger.first
|
110
|
+
end
|
111
|
+
|
112
|
+
# Scheduling unit.
|
113
|
+
# Current implementation is based on 'rufus-scheduler' gem thus each
|
114
|
+
# scheduling type has own arguments:
|
115
|
+
# 1. Scheduling type 'cron' has 'unit' = '00 09 * * *'
|
116
|
+
# 2. Scheduling type 'interval' has 'unit' = '2h'
|
117
|
+
# 3. Scheduling type 'every' has 'unit' = '3h'
|
118
|
+
# 4. Scheduling type 'in' has 'unit' = '10d'
|
119
|
+
# 5. Scheduling type 'at' has 'unit' = '2014/12/24 2000'
|
120
|
+
def unit
|
121
|
+
trigger.last
|
122
|
+
end
|
123
|
+
|
104
124
|
def detect_cc(sys)
|
105
125
|
opts = props
|
106
126
|
opts["cc"] = CC.new.detect(opts["cc"], sys)
|
@@ -125,13 +145,27 @@ module Lazylead
|
|
125
145
|
Postman.new
|
126
146
|
end
|
127
147
|
end
|
148
|
+
|
149
|
+
private
|
150
|
+
|
151
|
+
# Parse scheduling #type and #unit
|
152
|
+
def trigger
|
153
|
+
@trigger ||= begin
|
154
|
+
trg = schedule.split(":")
|
155
|
+
unless trg.size == 2
|
156
|
+
raise "ll-007: illegal schedule format '#{schedule}'"
|
157
|
+
end
|
158
|
+
trg.map(&:strip).map(&:chomp)
|
159
|
+
end
|
160
|
+
end
|
128
161
|
end
|
129
162
|
|
130
163
|
# A task with extended logging
|
131
164
|
# @see Lazylead::ORM::Task
|
132
165
|
class VerboseTask
|
133
166
|
extend Forwardable
|
134
|
-
def_delegators :@orig, :id, :name, :team, :to_s, :inspect, :props
|
167
|
+
def_delegators :@orig, :id, :name, :team, :to_s, :inspect, :props, :type,
|
168
|
+
:unit
|
135
169
|
|
136
170
|
def initialize(orig, log = Log.new)
|
137
171
|
@orig = orig
|
data/lib/lazylead/opts.rb
CHANGED
@@ -23,6 +23,7 @@
|
|
23
23
|
# OR OTHER DEALINGS IN THE SOFTWARE.
|
24
24
|
|
25
25
|
require "forwardable"
|
26
|
+
require_relative "salt"
|
26
27
|
|
27
28
|
module Lazylead
|
28
29
|
#
|
@@ -64,5 +65,16 @@ module Lazylead
|
|
64
65
|
def jira_fields
|
65
66
|
to_h.fetch("fields", "").split(",").map(&:to_sym)
|
66
67
|
end
|
68
|
+
|
69
|
+
# Decrypt particular option using cryptography salt
|
70
|
+
# @param key option to be decrypted
|
71
|
+
# @param sid the name of the salt to be used for the description
|
72
|
+
# @see Lazylead::Salt
|
73
|
+
def decrypt(key, sid)
|
74
|
+
text = to_h[key]
|
75
|
+
return text if text.blank? || text.nil?
|
76
|
+
return Salt.new(sid).decrypt(text) if ENV.key? sid
|
77
|
+
text
|
78
|
+
end
|
67
79
|
end
|
68
80
|
end
|
data/lib/lazylead/schedule.rb
CHANGED
@@ -34,23 +34,18 @@ module Lazylead
|
|
34
34
|
# Copyright:: Copyright (c) 2019-2020 Yurii Dubinka
|
35
35
|
# License:: MIT
|
36
36
|
class Schedule
|
37
|
-
|
38
|
-
# The minimum time period for cron is 1 minute and it's not suitable for
|
39
|
-
# unit testing, thus its better to introduce new types which allows to
|
40
|
-
# schedule some task once or at particular time period like in next 200ms).
|
41
|
-
# For cron expressions we should define separate test suite which will test
|
42
|
-
# in parallel without blocking main CI process.
|
43
|
-
def initialize(log = Log.new, cling = true)
|
37
|
+
def initialize(log: Log.new, cling: true, trigger: Rufus::Scheduler.new)
|
44
38
|
@log = log
|
45
39
|
@cling = cling
|
46
|
-
@trigger =
|
40
|
+
@trigger = trigger
|
47
41
|
end
|
48
42
|
|
49
|
-
# @todo #/DEV error code is required for
|
50
|
-
# application.
|
43
|
+
# @todo #/DEV error code is required for each 'raise' statement within the
|
44
|
+
# application. Align the naming of existing one, the error code should be
|
45
|
+
# like ll-xxx.
|
51
46
|
def register(task)
|
52
47
|
raise "ll-002: task can't be a null" if task.nil?
|
53
|
-
@trigger.
|
48
|
+
@trigger.method(task.type).call(task.unit) do
|
54
49
|
ActiveRecord::Base.connection_pool.with_connection do
|
55
50
|
ORM::VerboseTask.new(task, @log).exec
|
56
51
|
end
|
@@ -60,7 +55,9 @@ module Lazylead
|
|
60
55
|
|
61
56
|
# @todo #/DEV inspect the current execution status. This method should
|
62
57
|
# support several format for output, by default is `json`.
|
63
|
-
def ps
|
58
|
+
def ps
|
59
|
+
@log.debug "#{self}#ps"
|
60
|
+
end
|
64
61
|
|
65
62
|
def join
|
66
63
|
@trigger.join if @cling
|
@@ -80,11 +77,15 @@ module Lazylead
|
|
80
77
|
end
|
81
78
|
|
82
79
|
def register(task)
|
83
|
-
@log.debug
|
80
|
+
@log.debug "Task registered: #{task}"
|
84
81
|
end
|
85
82
|
|
86
|
-
def ps
|
83
|
+
def ps
|
84
|
+
@log.debug "#{self}#ps"
|
85
|
+
end
|
87
86
|
|
88
|
-
def join
|
87
|
+
def join
|
88
|
+
@log.debug "#{self}#join"
|
89
|
+
end
|
89
90
|
end
|
90
91
|
end
|
data/lib/lazylead/system/jira.rb
CHANGED
@@ -150,6 +150,11 @@ module Lazylead
|
|
150
150
|
@issue.key
|
151
151
|
end
|
152
152
|
|
153
|
+
def description
|
154
|
+
return "" if @issue.description.nil?
|
155
|
+
@issue.description
|
156
|
+
end
|
157
|
+
|
153
158
|
def summary
|
154
159
|
fields["summary"]
|
155
160
|
end
|
@@ -175,9 +180,24 @@ module Lazylead
|
|
175
180
|
end
|
176
181
|
|
177
182
|
def fields
|
183
|
+
return {} if @issue.nil?
|
184
|
+
return {} unless @issue.respond_to? :fields
|
185
|
+
return {} if @issue.fields.nil?
|
186
|
+
return {} unless @issue.fields.respond_to? :[]
|
178
187
|
@issue.fields
|
179
188
|
end
|
180
189
|
|
190
|
+
def [](name)
|
191
|
+
return "" if fields[name].nil? || fields[name].blank?
|
192
|
+
fields[name]
|
193
|
+
end
|
194
|
+
|
195
|
+
def components
|
196
|
+
return [] unless @issue.respond_to? :components
|
197
|
+
return [] if @issue.components.nil?
|
198
|
+
@issue.components.map(&:name)
|
199
|
+
end
|
200
|
+
|
181
201
|
def history
|
182
202
|
return [] unless @issue.respond_to? :changelog
|
183
203
|
return [] if @issue.changelog == nil? || @issue.changelog.empty?
|
@@ -206,6 +226,25 @@ module Lazylead
|
|
206
226
|
def post(markdown)
|
207
227
|
@issue.comments.build.save!(body: markdown)
|
208
228
|
end
|
229
|
+
|
230
|
+
def remote_links
|
231
|
+
@issue.remotelink.all
|
232
|
+
end
|
233
|
+
|
234
|
+
def attachments
|
235
|
+
@issue.attachments
|
236
|
+
end
|
237
|
+
|
238
|
+
def add_label(label, *more)
|
239
|
+
labels = @issue.labels
|
240
|
+
labels << label
|
241
|
+
labels += more if more.size.positive?
|
242
|
+
save!("fields" => { "labels" => labels.uniq })
|
243
|
+
end
|
244
|
+
|
245
|
+
def save!(opts)
|
246
|
+
@issue.save(opts)
|
247
|
+
end
|
209
248
|
end
|
210
249
|
|
211
250
|
# The jira issue comments
|
@@ -43,7 +43,7 @@ module Lazylead
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def run(sys, postman, opts)
|
46
|
-
|
46
|
+
Dir[File.join(__dir__, "*.rb")].sort.each { |f| require f }
|
47
47
|
rules = opts.slice("rules", ",")
|
48
48
|
.map(&:constantize)
|
49
49
|
.map(&:new)
|
@@ -53,12 +53,6 @@ module Lazylead
|
|
53
53
|
.each(&:post)
|
54
54
|
postman.send opts.merge(tickets: raised) unless raised.empty?
|
55
55
|
end
|
56
|
-
|
57
|
-
# Load all ticket accuracy rules for future verification
|
58
|
-
def require_rules
|
59
|
-
rules = File.dirname(__FILE__)
|
60
|
-
$LOAD_PATH.unshift(rules) unless $LOAD_PATH.include?(rules)
|
61
|
-
end
|
62
56
|
end
|
63
57
|
end
|
64
58
|
|
@@ -85,7 +79,9 @@ module Lazylead
|
|
85
79
|
|
86
80
|
# Post the comment with score and accuracy to the ticket.
|
87
81
|
def post
|
88
|
-
|
82
|
+
return if @opts.key? "silent"
|
83
|
+
@issue.post comment
|
84
|
+
@issue.add_label "LL.accuracy", "#{(@accuracy / 10) * 10}%"
|
89
85
|
end
|
90
86
|
|
91
87
|
# The jira comment in markdown format
|
@@ -22,22 +22,18 @@
|
|
22
22
|
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
23
23
|
# OR OTHER DEALINGS IN THE SOFTWARE.
|
24
24
|
|
25
|
-
require_relative "../../log"
|
26
|
-
require_relative "../../email"
|
27
|
-
require_relative "../../version"
|
28
|
-
require_relative "../../postman"
|
29
25
|
require_relative "requirement"
|
30
26
|
|
31
27
|
module Lazylead
|
32
28
|
# A requirement that Jira field "Affects Version/s" provided by the reporter.
|
33
|
-
class
|
29
|
+
class AffectedBuild < Requirement
|
34
30
|
def initialize(score = 0.5)
|
35
31
|
super "Affected build", score, "Affects Version/s"
|
36
32
|
end
|
37
33
|
|
38
34
|
# @return true if an issue has non-empty "Affects Version/s" field
|
39
35
|
def passed(issue)
|
40
|
-
|
36
|
+
non_blank? issue, "versions"
|
41
37
|
end
|
42
38
|
end
|
43
39
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# The MIT License
|
4
|
+
#
|
5
|
+
# Copyright (c) 2019-2020 Yurii Dubinka
|
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"),
|
9
|
+
# to deal in the Software without restriction, including without limitation
|
10
|
+
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
11
|
+
# and/or sell copies of the Software, and to permit persons to whom
|
12
|
+
# the Software is furnished to do so, subject to the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be included
|
15
|
+
# in all 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 NON-INFRINGEMENT. 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,
|
22
|
+
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
23
|
+
# OR OTHER DEALINGS IN THE SOFTWARE.
|
24
|
+
|
25
|
+
require_relative "requirement"
|
26
|
+
|
27
|
+
module Lazylead
|
28
|
+
# Check that ticket has an attachment.
|
29
|
+
class Attachment < Lazylead::Requirement
|
30
|
+
def initialize(desc, score, field)
|
31
|
+
super(desc, score, field)
|
32
|
+
end
|
33
|
+
|
34
|
+
def passed(issue)
|
35
|
+
issue.attachments.any?(&method(:matching))
|
36
|
+
end
|
37
|
+
|
38
|
+
# Check a single attachment from ticket.
|
39
|
+
# Potential extension point for custom verification logic.
|
40
|
+
def matching(attachment)
|
41
|
+
!attachment.nil?
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|