Skip to content

Commit

Permalink
#334: alert if predefined users have no tickets from particular filte…
Browse files Browse the repository at this point in the history
…r/jql
  • Loading branch information
dgroup committed Feb 14, 2021
1 parent 63b58d7 commit 89985d5
Show file tree
Hide file tree
Showing 5 changed files with 276 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/lazylead/task/alert/alertif.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ module Task
# - fetch issues from remote ticketing system by query
# - evaluate set of rules for each ticket
# - send an email
# @todo #334:DEV AlertIf should support rules for bulk issues. For now each rule works per issue
class AlertIf
def run(sys, postman, opts)
Requires.new(__dir__).load
Expand Down
94 changes: 94 additions & 0 deletions lib/lazylead/task/loading.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# frozen_string_literal: true

# The MIT License
#
# Copyright (c) 2019-2020 Yurii Dubinka
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom
# the Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
# OR OTHER DEALINGS IN THE SOFTWARE.

require "date"
require_relative "../log"
require_relative "../opts"
require_relative "../system/jira"

module Lazylead
module Task
# Notification about team loading
class Loading
def initialize(log = Log.new)
@log = log
end

def run(sys, postman, opts)
assignments = sys.issues(opts["jql"])
.group_by(&:assignee)
.map { |user, tasks| [user.id, Assignment.new(user, tasks)] }
.to_h
opts.slice("team", ",")
.map { |m| m.split(":") }
.each { |id, name| assignments[id] = Free.new(id, name) unless assignments.key? id }
return if assignments.empty?
postman.send opts.merge(assignments: assignments)
end
end

# The teammate's tickets.
class Assignment
extend Forwardable
def_delegators :@user, :id, :name
def_delegators :@tasks, :size

def initialize(user, tasks = [])
@user = user
@tasks = tasks
end

def free?
return true if @tasks.nil?
@tasks.empty?
end

def next
@tasks.reject { |t| t.duedate.nil? }.map { |t| t.duedate.to_date }.min
end

def to_s
"#{id} has #{total} tasks"
end
end

# The teammate without tasks.
class Free
attr_reader :id, :name

def initialize(id, name)
@id = id
@name = name
end

def free?
true
end

def next
""
end
end
end
end
117 changes: 117 additions & 0 deletions lib/messages/loading.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
<!DOCTYPE html>
<html lang="en">
<head>
<style> /* CSS styles taken from https://github.com/yegor256/tacit */
th {
font-weight: 600
}

table tr {
border-bottom-width: 2.16px
}

table tr th {
border-bottom-width: 2.16px
}

table tr td, table tr th {
overflow: hidden;
padding: 5.4px 3.6px;
line-height: 20px;
}

.auto {
min-width: auto;
white-space: nowrap;
}

a {
color: #275a90;
text-decoration: none
}

a:hover {
text-decoration: underline
}

* {
border: 0;
border-collapse: separate;
border-spacing: 0;
box-sizing: border-box;
margin: 0;
max-width: 100%;
padding: 0;
vertical-align: baseline;
font-family: system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 13px;
font-stretch: normal;
font-style: normal;
font-weight: 400;
}

html, body {
width: 100%
}

html {
height: 100%
}

body {
background: #fff;
color: #1a1919;
padding: 36px
}
</style>
<title>Loading</title>
</head>
<body>
<table summary="tickets">
<tr>
<th id="uid">ID</th>
<th id="name">User</th>
<th id="total">
<a href="https://jira.spring.io/issues/?jql=<%= CGI.escape(jql) %>">Assigned From</a>
</th>
<th id="duedate">Next Due date</th>
</tr>
<% assignments.each do |teammate, assignment| %>
<% if assignment.free? %>
<tr style="background: #FCEC88">
<% else %>
<tr>
<% end %>
<td>
<div class="auto"><a href="<%= user_link %>"><%= teammate %></a></div>
</td>
<td>
<div class="auto"><%= assignment.name %></div>
</td>
<td>
<div class="auto">
<% if assignment.free? %>
<span style="color: red">0</span>
<% else %>
<a href="https://jira.spring.io/issues/?jql=<%= CGI.escape("#{jql} and assignee=#{teammate}") %>"><%= assignment.size %></a>
<% end %>
</div>
</td>
<td>
<div class="auto">
<% if assignment.next.kind_of?(Date) && Date.current.after?(assignment.next) %>
<span style="color: red"><%= assignment.next %></span>
<% else %>
<%= assignment.next %>
<% end %>
</div>
</td>
</tr>
<% end %>
</table>
<br/>
<p>Posted by
<a href="https://github.com/dgroup/lazylead">lazylead v<%= version %></a>.
</p>
</body>
</html>
9 changes: 9 additions & 0 deletions test/lazylead/system/jira_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -194,5 +194,14 @@ def save!(body)
"context_path" => ""
).issues("key=DATAJDBC-480")
end

test "users from particular group found" do
refute_empty Jira.new(
"username" => ENV["JIRA_USER"],
"password" => ENV["JIRA_PASS"],
"site" => "https://jira.spring.io",
"context_path" => ""
).users("jira-administrators")
end
end
end
55 changes: 55 additions & 0 deletions test/lazylead/task/loading_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# frozen_string_literal: true

# The MIT License
#
# Copyright (c) 2019-2020 Yurii Dubinka
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom
# the Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
# OR OTHER DEALINGS IN THE SOFTWARE.

require "mail"

require_relative "../../test"
require_relative "../../../lib/lazylead/smtp"
require_relative "../../../lib/lazylead/opts"
require_relative "../../../lib/lazylead/postman"
require_relative "../../../lib/lazylead/task/loading"

module Lazylead
class LoadingTest < Lazylead::Test
test "notify about team loading" do
Lazylead::Smtp.new.enable
Task::Loading.new.run(
NoAuthJira.new("https://jira.spring.io"),
Postman.new,
Opts.new(
"to" => "lead@company.com",
"from" => "ll@company.com",
"jql" => "key=STS-3599",
"team" => "mclaren:Tom McLaren,milesparker:Mi Pa",
"user_link" => "https://user.com?id=",
"fields" => "description,assignee,component,priority,summary,duedate",
"subject" => "[LL] Team loading",
"template" => "lib/messages/loading.erb"
)
)
assert_email "[LL] Team loading",
%w[DATAJDBC-480 01-Apr-2020 Minor Mark\ Paluch tom,mike,bob EntityInstantiators]
end
end
end

0 comments on commit 89985d5

Please sign in to comment.