lazylead 0.5.0 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +4 -3
  3. data/bin/lazylead +6 -4
  4. data/lazylead.gemspec +4 -3
  5. data/lib/lazylead/cli/app.rb +11 -3
  6. data/lib/lazylead/email.rb +0 -20
  7. data/lib/lazylead/exchange.rb +16 -29
  8. data/lib/lazylead/log.rb +2 -1
  9. data/lib/lazylead/model.rb +7 -0
  10. data/lib/lazylead/opts.rb +49 -1
  11. data/lib/lazylead/postman.rb +18 -17
  12. data/lib/lazylead/smtp.rb +3 -1
  13. data/lib/lazylead/system/jira.rb +30 -8
  14. data/lib/lazylead/task/accuracy/accuracy.rb +10 -1
  15. data/lib/lazylead/task/accuracy/logs.rb +7 -3
  16. data/lib/lazylead/task/accuracy/records.rb +1 -1
  17. data/lib/lazylead/task/accuracy/servers.rb +1 -1
  18. data/lib/lazylead/task/accuracy/stacktrace.rb +50 -10
  19. data/lib/lazylead/task/accuracy/testcase.rb +23 -6
  20. data/lib/lazylead/task/assignment.rb +96 -0
  21. data/lib/lazylead/task/fix_version.rb +6 -0
  22. data/lib/lazylead/task/svn/diff.rb +77 -0
  23. data/lib/lazylead/task/svn/grep.rb +132 -0
  24. data/lib/lazylead/task/svn/touch.rb +101 -0
  25. data/lib/lazylead/version.rb +1 -1
  26. data/lib/messages/illegal_assignee_change.erb +123 -0
  27. data/lib/messages/illegal_fixversion_change.erb +8 -0
  28. data/lib/messages/svn_diff.erb +110 -0
  29. data/lib/messages/{svn_log.erb → svn_diff_attachment.erb} +19 -9
  30. data/lib/messages/svn_grep.erb +114 -0
  31. data/test/lazylead/model_test.rb +10 -0
  32. data/test/lazylead/opts_test.rb +35 -0
  33. data/test/lazylead/postman_test.rb +8 -5
  34. data/test/lazylead/system/jira_test.rb +14 -7
  35. data/test/lazylead/task/accuracy/logs_test.rb +62 -2
  36. data/test/lazylead/task/accuracy/score_test.rb +46 -0
  37. data/test/lazylead/task/accuracy/stacktrace_test.rb +227 -0
  38. data/test/lazylead/task/accuracy/testcase_test.rb +49 -0
  39. data/test/lazylead/task/assignment_test.rb +53 -0
  40. data/test/lazylead/task/fix_version_test.rb +1 -0
  41. data/test/lazylead/task/savepoint_test.rb +7 -4
  42. data/test/lazylead/task/svn/diff_test.rb +97 -0
  43. data/test/lazylead/task/svn/grep_test.rb +103 -0
  44. data/test/lazylead/task/{touch_test.rb → svn/touch_test.rb} +7 -34
  45. data/upgrades/sqlite/999.testdata.sql +2 -1
  46. metadata +48 -20
  47. data/lib/lazylead/task/touch.rb +0 -119
@@ -0,0 +1,101 @@
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 "tmpdir"
26
+ require "nokogiri"
27
+ require "active_support/core_ext/hash/conversions"
28
+ require_relative "../../salt"
29
+ require_relative "../../opts"
30
+
31
+ module Lazylead
32
+ module Task
33
+ module Svn
34
+ #
35
+ # Send notification about modification of critical files in svn repo.
36
+ #
37
+ class Touch
38
+ def initialize(log = Log.new)
39
+ @log = log
40
+ end
41
+
42
+ def run(_, postman, opts)
43
+ files = opts.slice("files", ",")
44
+ commits = touch(files, opts)
45
+ postman.send(opts.merge(entries: commits)) unless commits.empty?
46
+ end
47
+
48
+ # Return all svn commits for a particular date range, which are touching
49
+ # somehow the critical files within the svn repo.
50
+ def touch(files, opts)
51
+ xpath = files.map { |f| "contains(text(),\"#{f}\")" }.join(" or ")
52
+ svn_log(opts).xpath("//logentry[paths/path[#{xpath}]]")
53
+ .map(&method(:to_entry))
54
+ .each do |e|
55
+ if e.paths.path.respond_to? :delete_if
56
+ e.paths.path.delete_if { |p| files.none? { |f| p.include? f } }
57
+ end
58
+ end
59
+ end
60
+
61
+ # Return all svn commits for particular date range in repo
62
+ def svn_log(opts)
63
+ now = if opts.key? "now"
64
+ DateTime.parse(opts["now"])
65
+ else
66
+ DateTime.now
67
+ end
68
+ start = (now.to_time - opts["period"].to_i).to_datetime
69
+ cmd = [
70
+ "svn log --no-auth-cache",
71
+ "--username #{opts.decrypt('svn_user', 'svn_salt')}",
72
+ "--password #{opts.decrypt('svn_password', 'svn_salt')}",
73
+ "--xml -v -r {#{start}}:{#{now}} #{opts['svn_url']}"
74
+ ]
75
+ raw = `#{cmd.join(" ")}`
76
+ Nokogiri.XML(raw, nil, "UTF-8")
77
+ end
78
+
79
+ # Convert single revision(XML text) to entry object.
80
+ # Entry object is a simple ruby struct object.
81
+ def to_entry(xml)
82
+ e = to_struct(Hash.from_xml(xml.to_s.strip)).logentry
83
+ if e.paths.path.respond_to? :each
84
+ e.paths.path.each(&:strip!)
85
+ else
86
+ e.paths.path.strip!
87
+ end
88
+ e
89
+ end
90
+
91
+ # Make a simple ruby struct object from hash hierarchically,
92
+ # considering nested hash(es) (if applicable)
93
+ def to_struct(hsh)
94
+ OpenStruct.new(
95
+ hsh.transform_values { |v| v.is_a?(Hash) ? to_struct(v) : v }
96
+ )
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -23,5 +23,5 @@
23
23
  # OR OTHER DEALINGS IN THE SOFTWARE.
24
24
 
25
25
  module Lazylead
26
- VERSION = "0.5.0"
26
+ VERSION = "0.6.2"
27
27
  end
@@ -0,0 +1,123 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <style>
5
+ /* CSS styles taken from https://github.com/yegor256/tacit */
6
+ th {
7
+ font-weight: 600
8
+ }
9
+
10
+ table tr {
11
+ border-bottom-width: 2.16px
12
+ }
13
+
14
+ table tr th {
15
+ border-bottom-width: 2.16px
16
+ }
17
+
18
+ table tr td, table tr th {
19
+ overflow: hidden;
20
+ padding: 5.4px 3.6px
21
+ }
22
+
23
+ a {
24
+ color: #275a90;
25
+ text-decoration: none
26
+ }
27
+
28
+ a:hover {
29
+ text-decoration: underline
30
+ }
31
+
32
+ pre, code, kbd, samp, var, output {
33
+ font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
34
+ font-size: 13px
35
+ }
36
+
37
+ pre code {
38
+ background: none;
39
+ border: 0;
40
+ line-height: 29.7px;
41
+ padding: 0
42
+ }
43
+
44
+ code, kbd {
45
+ background: #daf1e0;
46
+ border-radius: 3.6px;
47
+ color: #2a6f3b;
48
+ display: inline-block;
49
+ line-height: 18px;
50
+ padding: 3.6px 6.3px 2.7px
51
+ }
52
+
53
+ * {
54
+ border: 0;
55
+ border-collapse: separate;
56
+ border-spacing: 0;
57
+ box-sizing: border-box;
58
+ margin: 0;
59
+ max-width: 100%;
60
+ padding: 0;
61
+ vertical-align: baseline;
62
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
63
+ font-size: 13px;
64
+ font-stretch: normal;
65
+ font-style: normal;
66
+ font-weight: 400;
67
+ line-height: 29.7px
68
+ }
69
+
70
+ html, body {
71
+ width: 100%
72
+ }
73
+
74
+ html {
75
+ height: 100%
76
+ }
77
+
78
+ body {
79
+ background: #fff;
80
+ color: #1a1919;
81
+ padding: 36px
82
+ }
83
+ </style>
84
+ <title>Not authorized "Assignee" change</title>
85
+ </head>
86
+ <body>
87
+ <p>Hi,</p>
88
+
89
+ <p>The <span style='font-weight:bold'>'Assignee'</span> for the following
90
+ ticket(s) changed by not authorized person(s):</p>
91
+ <table summary="ticket(s) where assignee changed">
92
+ <tr>
93
+ <th id="key">Key</th>
94
+ <th id="priority">Priority</th>
95
+ <th id="when">When</th>
96
+ <th id="who">Who</th>
97
+ <th id="to">To</th>
98
+ <th id="summary">Summary</th>
99
+ <th id="reporter">Reporter</th>
100
+ </tr>
101
+ <% assignees.each do |a| %>
102
+ <tr>
103
+ <td><a href='<%= a.issue.url %>'><%= a.issue.key %></a></td>
104
+ <td><%= a.issue.priority %></td>
105
+ <td><%= DateTime.parse(a.last["created"])
106
+ .strftime('%d-%b-%Y %I:%M:%S %p') %></td>
107
+ <td><span style='color: red'><%= a.last["author"]["displayName"] %></span>
108
+ (<%= a.last["author"]["name"] %>)
109
+ </td>
110
+ <td><%= a.to %></td>
111
+ <td><%= a.issue.summary %></td>
112
+ <td><%= a.issue.reporter.name %></td>
113
+ </tr>
114
+ <% end %>
115
+ </table>
116
+
117
+ <p>Authorized person(s) are: <code><%= allowed %></code>.</p>
118
+
119
+ <p>Posted by
120
+ <a href="https://github.com/dgroup/lazylead">lazylead v<%= version %></a>.
121
+ </p>
122
+ </body>
123
+ </html>
@@ -92,6 +92,8 @@
92
92
  <tr>
93
93
  <th id="key">Key</th>
94
94
  <th id="priority">Priority</th>
95
+ <th id="from">From</th>
96
+ <th id="to">To</th>
95
97
  <th id="when">When</th>
96
98
  <th id="who">Who</th>
97
99
  <th id="reporter">Reporter</th>
@@ -101,6 +103,12 @@
101
103
  <tr>
102
104
  <td><a href='<%= v.issue.url %>'><%= v.issue.key %></a></td>
103
105
  <td><%= v.issue.priority %></td>
106
+ <td><%= v.last["items"]
107
+ .select { |h| h["field"] == "Fix Version" }
108
+ .map { |h| h["fromString"] }
109
+ .reject(&:blank?)
110
+ .join(",") %></td>
111
+ <td><%= v.to %></td>
104
112
  <td><%= DateTime.parse(v.last["created"])
105
113
  .strftime('%d-%b-%Y %I:%M:%S %p') %></td>
106
114
  <td><span style='color: red'><%= v.last["author"]["displayName"] %></span>
@@ -0,0 +1,110 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <style>
5
+ /* CSS styles taken from https://github.com/yegor256/tacit */
6
+ pre, code, kbd, samp, var, output {
7
+ font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
8
+ font-size: 14.4px
9
+ }
10
+
11
+ pre code {
12
+ background: none;
13
+ border: 0;
14
+ line-height: 29.7px;
15
+ padding: 0
16
+ }
17
+
18
+ code, kbd {
19
+ background: #daf1e0;
20
+ border-radius: 3.6px;
21
+ color: #2a6f3b;
22
+ display: inline-block;
23
+ line-height: 18px;
24
+ padding: 3.6px 6.3px 2.7px
25
+ }
26
+
27
+ a {
28
+ color: #275a90;
29
+ text-decoration: none
30
+ }
31
+
32
+ a:hover {
33
+ text-decoration: underline
34
+ }
35
+
36
+ * {
37
+ border: 0;
38
+ border-collapse: separate;
39
+ border-spacing: 0;
40
+ box-sizing: border-box;
41
+ margin: 0;
42
+ max-width: 100%;
43
+ padding: 0;
44
+ vertical-align: baseline;
45
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
46
+ font-size: 13px;
47
+ font-stretch: normal;
48
+ font-style: normal;
49
+ font-weight: 400;
50
+ line-height: 29.7px
51
+ }
52
+
53
+ html, body {
54
+ width: 100%
55
+ }
56
+
57
+ html {
58
+ height: 100%
59
+ }
60
+
61
+ body {
62
+ background: #fff;
63
+ color: #1a1919;
64
+ padding: 36px
65
+ }
66
+
67
+ .commit {
68
+ min-width: 100%;
69
+ border-radius: 3.5px;
70
+ overflow: hidden;
71
+ display: inline-block;
72
+ line-height: 15px;
73
+ font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
74
+ border: 1px solid #BCC6CC;
75
+ }
76
+
77
+ .commit * {
78
+ padding-left: 4px;
79
+ font-size: 8px;
80
+ line-height: 12px;
81
+ }
82
+ </style>
83
+ <title>SVN log</title>
84
+ </head>
85
+ <body>
86
+ <p>Hi,</p>
87
+ <p>The following file(s) changed since <code><%= since_rev %></code> rev in
88
+ <a href="<%= svn_url %>"><%= svn_url %></a>:</p>
89
+ <% stdout.split("------------------------------------------------------------------------").reject(&:blank?).reverse.each do |commit| %>
90
+ <div class="commit">
91
+ <% commit.split("\n").reject(&:blank?).each_with_index do |line, index| %>
92
+ <p style="background: gainsboro;">
93
+ <% if index.zero? %>
94
+ <% details = line.split("|").map(&:strip).reject(&:blank?) %>
95
+ <a href="<%= commit_url %><%= details[0][1..-1] %>"><%= details[0] %></a>
96
+ by <a href="<%= user %><%= details[1] %>"><%= details[1] %></a>
97
+ at <span style="color: #275a90;"><%= details[2] %></span>
98
+ <% end %>
99
+ <% if index == 1 %>
100
+ <span style="padding-left: 4px"><%= line %></span>
101
+ <% end %>
102
+ </p>
103
+ <% end %>
104
+ </div>
105
+ <% end %>
106
+ <p>Posted by
107
+ <a href="https://github.com/dgroup/lazylead">lazylead v<%= version %></a>.
108
+ </p>
109
+ </body>
110
+ </html>
@@ -64,7 +64,7 @@
64
64
  padding: 36px
65
65
  }
66
66
 
67
- .commit {
67
+ .commit, .table-of-contents {
68
68
  min-width: 100%;
69
69
  border-radius: 3.5px;
70
70
  overflow: hidden;
@@ -74,26 +74,36 @@
74
74
  border: 1px solid #BCC6CC;
75
75
  }
76
76
 
77
- .commit * {
77
+ .commit *, .table-of-contents * {
78
78
  padding-left: 4px;
79
79
  font-size: 8px;
80
80
  line-height: 15px;
81
81
  }
82
+
83
+ .table-of-contents {
84
+ border: none;
85
+ }
82
86
  </style>
83
87
  <title>SVN log</title>
84
88
  </head>
85
89
  <body>
86
90
  <p>Hi,</p>
87
- <p>The following file(s) changed since <code><%= since_rev %></code> rev in <a href="<%= svn_url %>"><%= svn_url %></a>:</p>
91
+ <p>Commit(s) since <code><%= since_rev %></code> revision in <a href="<%= svn_url %>"><%= svn_url %></a>:</p>
92
+ <div id="table-of-contents" class="table-of-contents">
93
+ <ul>
94
+ <% stdout.split("------------------------------------------------------------------------").reject(&:blank?).reverse.each do |commit| %>
95
+ <% details = commit.split("\n").reject(&:blank?).first.split("|").map(&:strip).reject(&:blank?) %>
96
+ <li><a href="#<%= details[0] %>"><%= details[0] %></a> by <%= details[1] %> at <%= details[2] %></li>
97
+ <% end %>
98
+ </ul>
99
+ </div>
88
100
  <% stdout.split("------------------------------------------------------------------------").reject(&:blank?).reverse.each do |commit| %>
89
101
  <div class="commit">
90
102
  <% commit.split("\n").reject(&:blank?).each_with_index do |line, index| %>
91
103
  <% if index.zero? %>
92
104
  <% details = line.split("|").map(&:strip).reject(&:blank?) %>
93
- <p style="background: gainsboro;">
94
- <a href="<%= commit_url %><%= details[0][1 .. -1] %>"><%= details[0] %></a>
95
- by<a href="<%= user %><%= details[1] %>"><%= details[1] %></a>
96
- at<span style="color: #275a90;"><%= details[2] %></span>
105
+ <p style="background: gainsboro;" id="<%= details[0] %>"><a href="<%= commit_url %><%= details[0][1..-1] %>"><%= details[0] %></a> by <a href="<%= user %><%= details[1] %>"><%= details[1] %></a> at <span style="color: #275a90;"><%= details[2] %></span>
106
+ <a href="#table-of-contents">&#8593;</a>
97
107
  </p>
98
108
  <% else %>
99
109
  <% if line.start_with?("+++") || line.start_with?("---") %>
@@ -103,12 +113,12 @@
103
113
  <% elsif line.start_with?("-") %>
104
114
  <p style="<%= "background: lightsalmon;" %>"><%= line.gsub(/[<>]/, '<' => '&lt;', '>' => '&gt;') %></p>
105
115
  <% else %>
106
- <p style="background: gainsboro;"><%= line.gsub(/[<>]/,'<' => '&lt;', '>' => '&gt;') %></p>
116
+ <p style="background: gainsboro;"><%= line.gsub(/[<>]/, '<' => '&lt;', '>' => '&gt;') %></p>
107
117
  <% end %>
108
118
  <% end %>
109
119
  <% end %>
110
120
  </div>
111
- <br/><br/><br/>
121
+ <br/>
112
122
  <% end %>
113
123
  <p>Posted by
114
124
  <a href="https://github.com/dgroup/lazylead">lazylead v<%= version %></a>.
@@ -0,0 +1,114 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <style>
5
+ /* CSS styles taken from https://github.com/yegor256/tacit */
6
+ pre, code, kbd, samp, var, output {
7
+ font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
8
+ font-size: 14.4px
9
+ }
10
+
11
+ pre code {
12
+ background: none;
13
+ border: 0;
14
+ line-height: 29.7px;
15
+ padding: 0
16
+ }
17
+
18
+ code, kbd {
19
+ background: #daf1e0;
20
+ border-radius: 3.6px;
21
+ color: #2a6f3b;
22
+ display: inline-block;
23
+ line-height: 18px;
24
+ padding: 3.6px 6.3px 2.7px
25
+ }
26
+
27
+ a {
28
+ color: #275a90;
29
+ text-decoration: none
30
+ }
31
+
32
+ a:hover {
33
+ text-decoration: underline
34
+ }
35
+
36
+ * {
37
+ border: 0;
38
+ border-collapse: separate;
39
+ border-spacing: 0;
40
+ box-sizing: border-box;
41
+ margin: 0;
42
+ max-width: 100%;
43
+ padding: 0;
44
+ vertical-align: baseline;
45
+ font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
46
+ font-size: 13px;
47
+ font-stretch: normal;
48
+ font-style: normal;
49
+ font-weight: 400;
50
+ line-height: 29.7px
51
+ }
52
+
53
+ html, body {
54
+ width: 100%
55
+ }
56
+
57
+ html {
58
+ height: 100%
59
+ }
60
+
61
+ body {
62
+ background: #fff;
63
+ color: #1a1919;
64
+ padding: 36px
65
+ }
66
+
67
+ .commit {
68
+ min-width: 100%;
69
+ border-radius: 3.5px;
70
+ overflow: hidden;
71
+ display: inline-block;
72
+ line-height: 15px;
73
+ font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
74
+ border: 1px solid #BCC6CC;
75
+ }
76
+
77
+ .commit * {
78
+ padding-left: 4px;
79
+ font-size: 8px;
80
+ line-height: 15px;
81
+ }
82
+ </style>
83
+ <title>SVN log</title>
84
+ </head>
85
+ <body>
86
+ <p>Hi,</p>
87
+ <p>The following file(s) contain text <code><%= text %></code> in
88
+ <a href="<%= svn_url %>"><%= svn_url %></a>:</p>
89
+ <% entries.each do |commit| %>
90
+ <div class="commit">
91
+ <p style="background: gainsboro;">
92
+ <a href="<%= commit_url %><%= commit.rev %>"><%= commit.msg %></a>
93
+ by <a href="<%= user %><%= commit.author %>"><%= commit.author %></a>
94
+ at <span style="color: #275a90;"><%= commit.time %></span>
95
+ </p>
96
+ <% commit.diff(text.split(",")).each do |line| %>
97
+ <% if line.start_with?("+++") || line.start_with?("---") %>
98
+ <p style="background: gainsboro;"><%= line.gsub(/[<>]/, '<' => '&lt;', '>' => '&gt;') %></p>
99
+ <% elsif text.split(",").any? { |t| line.include? t } %>
100
+ <p style="background: #F9F103;"><%= line.gsub(/[<>]/, '<' => '&lt;', '>' => '&gt;') %></p>
101
+ <% elsif line.start_with?("+") %>
102
+ <p style="<%= "background: darkseagreen;" %>"><%= line.gsub(/[<>]/, '<' => '&lt;', '>' => '&gt;') %></p>
103
+ <% elsif line.start_with?("-") %>
104
+ <p style="<%= "background: lightsalmon;" %>"><%= line.gsub(/[<>]/, '<' => '&lt;', '>' => '&gt;') %></p>
105
+ <% else %>
106
+ <p style="background: gainsboro;"><%= line.gsub(/[<>]/, '<' => '&lt;', '>' => '&gt;') %></p>
107
+ <% end %>
108
+ <% end %>
109
+ </div>
110
+ <% end %>
111
+ <p>Posted by<a href="https://github.com/dgroup/lazylead">lazylead
112
+ v<%= version %></a>.</p>
113
+ </body>
114
+ </html>