lazylead 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/ .dockerignore +12 -0
- data/.0pdd.yml +5 -0
- data/.circleci/config.yml +50 -0
- data/.circleci/release_image.sh +13 -0
- data/.circleci/validate.sh +10 -0
- data/.docker/Dockerfile +31 -0
- data/.docker/build.sh +6 -0
- data/.docker/docker-compose.yml +23 -0
- data/.docker/readme.md +21 -0
- data/.gitattributes +9 -0
- data/.github/CODE_OF_CONDUCT.md +76 -0
- data/.github/CONTRIBUTING.md +9 -0
- data/.github/ISSUE_TEMPLATE.md +14 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +11 -0
- data/.github/tasks.yml +24 -0
- data/.github/trello.md +18 -0
- data/.gitignore +12 -0
- data/.pdd +5 -0
- data/.rubocop.yml +87 -0
- data/.ruby-version +1 -0
- data/.rultor.yml +31 -0
- data/.simplecov +16 -0
- data/.travis.yml +16 -0
- data/Gemfile +27 -0
- data/Guardfile +33 -0
- data/Rakefile +93 -0
- data/appveyor.yml +50 -0
- data/bin/.ruby-version +1 -0
- data/bin/lazylead +99 -0
- data/build.sh +6 -0
- data/deploy.sh +16 -0
- data/lazylead.gemspec +106 -0
- data/lib/lazylead.rb +52 -0
- data/lib/lazylead/allocated.rb +56 -0
- data/lib/lazylead/cli/app.rb +87 -0
- data/lib/lazylead/confluence.rb +157 -0
- data/lib/lazylead/email.rb +74 -0
- data/lib/lazylead/exchange.rb +83 -0
- data/lib/lazylead/log.rb +71 -0
- data/lib/lazylead/model.rb +140 -0
- data/lib/lazylead/postman.rb +78 -0
- data/lib/lazylead/salt.rb +91 -0
- data/lib/lazylead/schedule.rb +88 -0
- data/lib/lazylead/smtp.rb +82 -0
- data/lib/lazylead/system/empty.rb +36 -0
- data/lib/lazylead/system/fake.rb +41 -0
- data/lib/lazylead/system/jira.rb +249 -0
- data/lib/lazylead/system/synced.rb +41 -0
- data/lib/lazylead/task/alert.rb +105 -0
- data/lib/lazylead/task/confluence_ref.rb +59 -0
- data/lib/lazylead/task/echo.rb +38 -0
- data/lib/lazylead/task/fix_version.rb +79 -0
- data/lib/lazylead/task/missing_comment.rb +53 -0
- data/lib/lazylead/version.rb +27 -0
- data/lib/messages/due_date_expired.erb +96 -0
- data/lib/messages/illegal_fixversion_change.erb +120 -0
- data/lib/messages/missing_comment.erb +128 -0
- data/license.txt +21 -0
- data/readme.md +160 -0
- data/test/lazylead/allocated_test.rb +51 -0
- data/test/lazylead/cli/app_test.rb +74 -0
- data/test/lazylead/confluence_test.rb +55 -0
- data/test/lazylead/exchange_test.rb +68 -0
- data/test/lazylead/model_test.rb +65 -0
- data/test/lazylead/salt_test.rb +42 -0
- data/test/lazylead/smoke_test.rb +38 -0
- data/test/lazylead/smtp_test.rb +65 -0
- data/test/lazylead/system/jira_test.rb +110 -0
- data/test/lazylead/task/confluence_ref_test.rb +66 -0
- data/test/lazylead/task/duedate_test.rb +126 -0
- data/test/lazylead/task/echo_test.rb +34 -0
- data/test/lazylead/task/fix_version_test.rb +52 -0
- data/test/lazylead/task/missing_comment_test.rb +56 -0
- data/test/lazylead/version_test.rb +36 -0
- data/test/sqlite_test.rb +80 -0
- data/test/test.rb +103 -0
- data/todo.yml +16 -0
- data/upgrades/sqlite/001-install-main-lazylead-tables.sql +63 -0
- data/upgrades/sqlite/999.testdata.sql +39 -0
- metadata +815 -0
@@ -0,0 +1,41 @@
|
|
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
|
+
module Lazylead
|
26
|
+
# Thread-save ticketing system.
|
27
|
+
class Synced
|
28
|
+
def initialize(sys)
|
29
|
+
@mutex = Mutex.new
|
30
|
+
@sys = sys
|
31
|
+
end
|
32
|
+
|
33
|
+
# @todo #/DEV Unit tests for 'issues' function
|
34
|
+
#
|
35
|
+
def issues(jql)
|
36
|
+
@mutex.synchronize do
|
37
|
+
@sys.issues jql
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,105 @@
|
|
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 "../log"
|
26
|
+
require_relative "../email"
|
27
|
+
require_relative "../version"
|
28
|
+
require_relative "../postman"
|
29
|
+
|
30
|
+
module Lazylead
|
31
|
+
#
|
32
|
+
# Email alerts about particular issue(s).
|
33
|
+
#
|
34
|
+
# Author:: Yurii Dubinka (yurii.dubinka@gmail.com)
|
35
|
+
# Copyright:: Copyright (c) 2019-2020 Yurii Dubinka
|
36
|
+
# License:: MIT
|
37
|
+
module Task
|
38
|
+
#
|
39
|
+
# Notify particular person about tickets based on pre-defined html template.
|
40
|
+
#
|
41
|
+
# The task supports the following features:
|
42
|
+
# - fetch issues from remote ticketing system by query
|
43
|
+
# - prepare email based on predefined template (*.erb)
|
44
|
+
# - send the required notifications pre-defined "addressee".
|
45
|
+
class Alert
|
46
|
+
def initialize(log = Log::NOTHING)
|
47
|
+
@log = log
|
48
|
+
end
|
49
|
+
|
50
|
+
def run(sys, postman, opts)
|
51
|
+
postman.send opts.merge(tickets: sys.issues(opts["sql"]))
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
#
|
56
|
+
# A task that sends notifications about issues to their assignees.
|
57
|
+
#
|
58
|
+
# The task supports the following features:
|
59
|
+
# - fetch issues from remote ticketing system by query
|
60
|
+
# - group all issues by assignee
|
61
|
+
# - prepare email based on predefined template (*.erb)
|
62
|
+
# - send the required notifications to each assignee
|
63
|
+
#
|
64
|
+
# The email message is sending to the assignee regarding all his/her issues,
|
65
|
+
# not like one email per each issue.
|
66
|
+
class AssigneeAlert
|
67
|
+
def initialize(log = Log::NOTHING)
|
68
|
+
@log = log
|
69
|
+
end
|
70
|
+
|
71
|
+
def run(sys, postman, opts)
|
72
|
+
sys.issues(opts["sql"])
|
73
|
+
.group_by(&:assignee)
|
74
|
+
.each do |a, t|
|
75
|
+
postman.send opts.merge(to: a.email, addressee: a.name, tickets: t)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
#
|
81
|
+
# A task that sends notifications about issues to their reporters.
|
82
|
+
#
|
83
|
+
# The task supports the following features:
|
84
|
+
# - fetch issues from remote ticketing system by query
|
85
|
+
# - group all issues by reporter
|
86
|
+
# - prepare email based on predefined template (*.erb)
|
87
|
+
# - send the required notifications to each reporter
|
88
|
+
#
|
89
|
+
# The email message is sending to the assignee regarding all his/her issues,
|
90
|
+
# not like one email per each issue.
|
91
|
+
class ReporterAlert
|
92
|
+
def initialize(log = Log::NOTHING)
|
93
|
+
@log = log
|
94
|
+
end
|
95
|
+
|
96
|
+
def run(sys, postman, opts)
|
97
|
+
sys.issues(opts["sql"])
|
98
|
+
.group_by(&:reporter)
|
99
|
+
.each do |a, t|
|
100
|
+
postman.send opts.merge(to: a.email, addressee: a.name, tickets: t)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,59 @@
|
|
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 "json"
|
26
|
+
require "faraday"
|
27
|
+
require_relative "../system/jira"
|
28
|
+
require_relative "../log"
|
29
|
+
require_relative "../confluence"
|
30
|
+
|
31
|
+
module Lazylead
|
32
|
+
module Task
|
33
|
+
# The lazylead task which adds reference to Confluence page
|
34
|
+
# in case if Confluence page was mentioned in issue comments.
|
35
|
+
# @todo #/DEV Support sub-task for link search. Potentially, the issue
|
36
|
+
# might have sub-tasks where discussion ongoing.
|
37
|
+
class ConfluenceRef
|
38
|
+
def initialize(log = Log::NOTHING)
|
39
|
+
@log = log
|
40
|
+
end
|
41
|
+
|
42
|
+
def run(sys, _, opts)
|
43
|
+
confluences = confluences(opts)
|
44
|
+
return if confluences.empty?
|
45
|
+
sys.issues(opts["jql"])
|
46
|
+
.map { |i| Link.new(i, sys, confluences) }
|
47
|
+
.each(&:fetch_links)
|
48
|
+
.select(&:need_link?)
|
49
|
+
.each(&:add_link)
|
50
|
+
end
|
51
|
+
|
52
|
+
def confluences(opts)
|
53
|
+
return [] if opts["confluences"].nil? || opts["confluences"].blank?
|
54
|
+
JSON.parse(opts["confluences"], object_class: OpenStruct)
|
55
|
+
.map { |c| Confluence.new(c) }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,38 @@
|
|
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
|
+
module Lazylead
|
26
|
+
module Task
|
27
|
+
# Lazylead task which prints to STDOUT the current class name and team.
|
28
|
+
#
|
29
|
+
# Author:: Yurii Dubinka (yurii.dubinka@gmail.com)
|
30
|
+
# Copyright:: Copyright (c) 2019-2020 Yurii Dubinka
|
31
|
+
# License:: MIT
|
32
|
+
class Echo
|
33
|
+
def run(_, _, _)
|
34
|
+
self.class.to_s
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,79 @@
|
|
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 "date"
|
26
|
+
require_relative "../system/jira"
|
27
|
+
require_relative "../log"
|
28
|
+
|
29
|
+
module Lazylead
|
30
|
+
module Task
|
31
|
+
# @todo #/DEV Each task should verify input arguments.
|
32
|
+
# The common API should be provided for each task.
|
33
|
+
class FixVersion
|
34
|
+
def initialize(log = Log::NOTHING)
|
35
|
+
@log = log
|
36
|
+
end
|
37
|
+
|
38
|
+
def run(sys, postman, opts)
|
39
|
+
allowed = opts["allowed"].split(",").map(&:strip).reject(&:blank?)
|
40
|
+
postman.send opts.merge(
|
41
|
+
versions: sys.issues(opts["jql"], expand: "changelog")
|
42
|
+
.map { |i| Version.new(i, allowed) }
|
43
|
+
.select(&:changed?)
|
44
|
+
)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Instance of "Fix Version" field for the particular task.
|
49
|
+
class Version
|
50
|
+
attr_reader :issue
|
51
|
+
|
52
|
+
def initialize(issue, allowed)
|
53
|
+
@issue = issue
|
54
|
+
@allowed = allowed
|
55
|
+
end
|
56
|
+
|
57
|
+
# Gives true when last change of "Fix Version" field was done
|
58
|
+
# by not authorized person.
|
59
|
+
def changed?
|
60
|
+
@allowed.none? do |a|
|
61
|
+
return false if last.nil?
|
62
|
+
a == last["author"]["name"]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Detect details about last change of "Fix Version" to non-null value
|
67
|
+
def last
|
68
|
+
return @last if defined? @last
|
69
|
+
@last = issue.history
|
70
|
+
.reverse
|
71
|
+
.find do |h|
|
72
|
+
h["items"].any? do |i|
|
73
|
+
i["field"] == "Fix Version" && !i["to"].nil?
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,53 @@
|
|
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 "../log"
|
26
|
+
require_relative "../postman"
|
27
|
+
|
28
|
+
module Lazylead
|
29
|
+
module Task
|
30
|
+
# A task which fetch issues by particular ticketing system query language
|
31
|
+
# and find issues where comments has no expected text.
|
32
|
+
#
|
33
|
+
# Example:
|
34
|
+
# you have a sub-task for demo session for your story;
|
35
|
+
# demo session is recorded, placed to ftp;
|
36
|
+
# nobody mentioned in comment the ftp location for recorded session.
|
37
|
+
# Such cases needs to be reported.
|
38
|
+
class MissingComment
|
39
|
+
def initialize(log = Log::NOTHING)
|
40
|
+
@log = log
|
41
|
+
end
|
42
|
+
|
43
|
+
def run(sys, postman, opts)
|
44
|
+
opts["details"] = "text '#{opts['text']}'" if opts["details"].blank?
|
45
|
+
postman.send opts.merge(
|
46
|
+
comments: sys.issues(opts["jql"])
|
47
|
+
.map { |i| Comments.new(i, sys) }
|
48
|
+
.reject { |c| c.body? opts["text"] }
|
49
|
+
)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,27 @@
|
|
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
|
+
module Lazylead
|
26
|
+
VERSION = "0.1.0"
|
27
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<style>
|
4
|
+
/* CSS styles taken from https://github.com/yegor256/tacit */
|
5
|
+
th {
|
6
|
+
font-weight: 600
|
7
|
+
}
|
8
|
+
|
9
|
+
table tr {
|
10
|
+
border-bottom-width: 2.16px
|
11
|
+
}
|
12
|
+
|
13
|
+
table tr th {
|
14
|
+
border-bottom-width: 2.16px
|
15
|
+
}
|
16
|
+
|
17
|
+
table tr td, table tr th {
|
18
|
+
overflow: hidden;
|
19
|
+
padding: 5.4px 3.6px
|
20
|
+
}
|
21
|
+
|
22
|
+
a {
|
23
|
+
color: #275a90;
|
24
|
+
text-decoration: none
|
25
|
+
}
|
26
|
+
|
27
|
+
a:hover {
|
28
|
+
text-decoration: underline
|
29
|
+
}
|
30
|
+
|
31
|
+
* {
|
32
|
+
border: 0;
|
33
|
+
border-collapse: separate;
|
34
|
+
border-spacing: 0;
|
35
|
+
box-sizing: border-box;
|
36
|
+
margin: 0;
|
37
|
+
max-width: 100%;
|
38
|
+
padding: 0;
|
39
|
+
vertical-align: baseline;
|
40
|
+
font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
|
41
|
+
font-size: 13px;
|
42
|
+
font-stretch: normal;
|
43
|
+
font-style: normal;
|
44
|
+
font-weight: 400;
|
45
|
+
line-height: 29.7px
|
46
|
+
}
|
47
|
+
|
48
|
+
html, body {
|
49
|
+
width: 100%
|
50
|
+
}
|
51
|
+
|
52
|
+
html {
|
53
|
+
height: 100%
|
54
|
+
}
|
55
|
+
|
56
|
+
body {
|
57
|
+
background: #fff;
|
58
|
+
color: #1a1919;
|
59
|
+
padding: 36px
|
60
|
+
}
|
61
|
+
</style>
|
62
|
+
<title>Expired due date</title>
|
63
|
+
</head>
|
64
|
+
<body>
|
65
|
+
<p>Hi <%= addressee %>,</p>
|
66
|
+
|
67
|
+
<p>The due date for these tasks is expired or seems to expire soon. Please plan
|
68
|
+
them accordingly or actualize the
|
69
|
+
<span style="font-weight:bold">"Due date"</span> field for the following
|
70
|
+
ticket(s):</p>
|
71
|
+
<table>
|
72
|
+
<tr>
|
73
|
+
<th>Key</th>
|
74
|
+
<th>Due date</th>
|
75
|
+
<th>Priority</th>
|
76
|
+
<th>Reporter</th>
|
77
|
+
<th>Summary</th>
|
78
|
+
</tr>
|
79
|
+
<% tickets.each do |ticket| %>
|
80
|
+
<tr>
|
81
|
+
<td><a href="<%= ticket.url %>"><%= ticket.key %></a></td>
|
82
|
+
<td><%= ticket.duedate %></td>
|
83
|
+
<td><%= ticket.priority %></td>
|
84
|
+
<td><%= ticket.reporter.name %></td>
|
85
|
+
<td><%= ticket.summary %></td>
|
86
|
+
</tr>
|
87
|
+
<% end %>
|
88
|
+
</table>
|
89
|
+
<p>In case you have no idea what date should be set - remove obsolete date or
|
90
|
+
ask your lead to fill it.</p>
|
91
|
+
|
92
|
+
<p>Posted by
|
93
|
+
<a href="https://github.com/dgroup/lazylead">lazylead v<%= version %></a>.
|
94
|
+
</p>
|
95
|
+
</body>
|
96
|
+
</html>
|