cutting_edge 0.0.1 → 0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +7 -2
- data/Gemfile.lock +130 -0
- data/LICENSE +68 -81
- data/Procfile +1 -0
- data/README.md +272 -74
- data/Rakefile +0 -5
- data/bin/cutting_edge +60 -45
- data/config.rb +55 -0
- data/cutting_edge.gemspec +33 -4
- data/heroku.config.rb +20 -0
- data/lib/cutting_edge.rb +1 -1
- data/lib/cutting_edge/app.rb +95 -19
- data/lib/cutting_edge/langs.rb +7 -1
- data/lib/cutting_edge/langs/python.rb +5 -1
- data/lib/cutting_edge/langs/ruby.rb +5 -1
- data/lib/cutting_edge/langs/rust.rb +5 -1
- data/lib/cutting_edge/public/images/error.svg +24 -0
- data/lib/cutting_edge/public/images/languages/python.svg +1 -0
- data/lib/cutting_edge/public/images/languages/ruby.svg +1 -0
- data/lib/cutting_edge/public/images/languages/rust.svg +1 -0
- data/lib/cutting_edge/public/images/ok.svg +24 -0
- data/lib/cutting_edge/public/javascript/clipboard.min.js +7 -0
- data/lib/cutting_edge/public/javascript/cuttingedge.js +53 -0
- data/lib/cutting_edge/public/stylesheets/primer.css +22 -0
- data/lib/cutting_edge/repo.rb +124 -18
- data/lib/cutting_edge/templates/_footer.html.erb +3 -0
- data/lib/cutting_edge/templates/_header.html.erb +8 -0
- data/lib/cutting_edge/templates/_overview.html.erb +9 -0
- data/lib/cutting_edge/templates/badge.svg.erb +39 -0
- data/lib/cutting_edge/templates/index.html.erb +62 -0
- data/lib/cutting_edge/templates/info.html.erb +101 -0
- data/lib/cutting_edge/templates/mail.html.erb +163 -0
- data/lib/cutting_edge/workers/badge.rb +33 -11
- data/lib/cutting_edge/workers/dependency.rb +36 -16
- data/lib/cutting_edge/workers/helpers.rb +8 -0
- data/lib/cutting_edge/workers/mail.rb +38 -0
- data/projects.yml +25 -0
- data/spec/app_spec.rb +115 -0
- data/spec/badge_worker_spec.rb +77 -0
- data/spec/dependency_worker_spec.rb +132 -0
- data/spec/email_worker_spec.rb +43 -0
- data/spec/fixtures.rb +180 -0
- data/spec/fixtures/projects.yml +27 -0
- data/spec/langs/python_spec.rb +47 -5
- data/spec/langs/ruby_spec.rb +105 -0
- data/spec/langs/rust_spec.rb +31 -0
- data/spec/repo_spec.rb +52 -0
- data/spec/spec_helper.rb +9 -1
- metadata +43 -15
- data/lib/cutting_edge/badge.rb +0 -46
@@ -0,0 +1,62 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
|
3
|
+
<html lang="en">
|
4
|
+
<head>
|
5
|
+
<meta charset="utf-8">
|
6
|
+
|
7
|
+
<title>Cutting Edge</title>
|
8
|
+
<meta name="description" content="Cutting Edge">
|
9
|
+
<meta name="author" content="Repotag">
|
10
|
+
|
11
|
+
<link rel="stylesheet" href="/stylesheets/primer.css">
|
12
|
+
|
13
|
+
</head>
|
14
|
+
|
15
|
+
<body>
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
<div class="container-lg">
|
20
|
+
|
21
|
+
<%= erb :_header %>
|
22
|
+
|
23
|
+
<br/>
|
24
|
+
<div class="pagehead">
|
25
|
+
<h1>Monitored Projects</h1>
|
26
|
+
</div>
|
27
|
+
<br/>
|
28
|
+
|
29
|
+
<%= erb :_overview %>
|
30
|
+
|
31
|
+
|
32
|
+
<br/>
|
33
|
+
<% if @hidden_repos_exist %>
|
34
|
+
<div id="hidden-repos">
|
35
|
+
<details class="details-reset mt-3">
|
36
|
+
<summary class="btn-link link-gray">List hidden repositories <span class="dropdown-caret"></summary>
|
37
|
+
<div class="p-3 mt-2">
|
38
|
+
<form id='token-form'>
|
39
|
+
<div class="form-group" id="token-form-group">
|
40
|
+
<div class="input-group">
|
41
|
+
<input class="form-control input-contrast" name="token" type="text" placeholder="Enter your CuttingEdge token here">
|
42
|
+
<span class="input-group-button">
|
43
|
+
<button class="btn" id="token-submit" type="submit" aria-label="Submit">
|
44
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="15" height="15"><path fill-rule="evenodd" d="M1.5 8a6.5 6.5 0 1113 0 6.5 6.5 0 01-13 0zM0 8a8 8 0 1116 0A8 8 0 010 8zm11.78-1.72a.75.75 0 00-1.06-1.06L6.75 9.19 5.28 7.72a.75.75 0 00-1.06 1.06l2 2a.75.75 0 001.06 0l4.5-4.5z"></path></svg>
|
45
|
+
</button>
|
46
|
+
</span>
|
47
|
+
</div>
|
48
|
+
<p class="note error" id="token-input-validation"></p>
|
49
|
+
</div>
|
50
|
+
</form>
|
51
|
+
</div>
|
52
|
+
</details>
|
53
|
+
</div>
|
54
|
+
<% end %>
|
55
|
+
|
56
|
+
<%= erb :_footer %>
|
57
|
+
</div>
|
58
|
+
|
59
|
+
<script src="/javascript/cuttingedge.js"></script>
|
60
|
+
<script async defer src="https://buttons.github.io/buttons.js"></script>
|
61
|
+
</body>
|
62
|
+
</html>
|
@@ -0,0 +1,101 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
|
3
|
+
<html lang="en">
|
4
|
+
<head>
|
5
|
+
<meta charset="utf-8">
|
6
|
+
|
7
|
+
<title>Dependency Overview</title>
|
8
|
+
<meta name="description" content="Cutting Edge">
|
9
|
+
<meta name="author" content="Repotag">
|
10
|
+
|
11
|
+
<link rel="stylesheet" href="/stylesheets/primer.css">
|
12
|
+
|
13
|
+
</head>
|
14
|
+
|
15
|
+
<body>
|
16
|
+
|
17
|
+
|
18
|
+
<div class="container-lg">
|
19
|
+
|
20
|
+
<%= erb :_header %>
|
21
|
+
|
22
|
+
<br/>
|
23
|
+
|
24
|
+
<div class="pagehead">
|
25
|
+
<h1 class="text-gray"><a href="<%= @project_url %>" class="link-gray"><%= @name %></a> (<image height="24" src="<%= "/images/languages/#{@language}.svg" %>"></image> <%= @language %>)</h1>
|
26
|
+
</div>
|
27
|
+
|
28
|
+
<div class="TableObject">
|
29
|
+
<div class="TableObject-item TableObject-item--primary">
|
30
|
+
<svg height="20" width="200"><image xlink:href="<%= @svg %>" /></svg>
|
31
|
+
</div>
|
32
|
+
<div class="TableObject-item">
|
33
|
+
<div>
|
34
|
+
<details class="dropdown details-reset details-overlay d-inline-block" id="embed">
|
35
|
+
<summary class="btn btn-sm" aria-haspopup="true">
|
36
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -2 16 16" width="16" height="16"><path fill-rule="evenodd" d="M2 13h4v1H2v-1zm5-6H2v1h5V7zm2 3V8l-3 3 3 3v-2h5v-2H9zM4.5 9H2v1h2.5V9zM2 12h2.5v-1H2v1zm9 1h1v2c-.02.28-.11.52-.3.7-.19.18-.42.28-.7.3H1c-.55 0-1-.45-1-1V4c0-.55.45-1 1-1h3c0-1.11.89-2 2-2 1.11 0 2 .89 2 2h3c.55 0 1 .45 1 1v5h-1V6H1v9h10v-2zM2 5h8c0-.55-.45-1-1-1H8c-.55 0-1-.45-1-1s-.45-1-1-1-1 .45-1 1-.45 1-1 1H3c-.55 0-1 .45-1 1z"></path></svg>
|
37
|
+
|
38
|
+
<span>Embed</span>
|
39
|
+
<div class="dropdown-caret"></div>
|
40
|
+
</summary>
|
41
|
+
|
42
|
+
<ul class="dropdown-menu dropdown-menu-sw">
|
43
|
+
<li><a class="dropdown-item clipboard" href="#" data-clipboard-text="<%= @md %>" onclick="getElementById('embed').removeAttribute('open')">Markdown link</a></li>
|
44
|
+
<li><a class="dropdown-item clipboard" href="#" data-clipboard-text="<%= @svg %>" onclick="getElementById('embed').removeAttribute('open')">Image Link</a></li>
|
45
|
+
</ul>
|
46
|
+
</details>
|
47
|
+
</div>
|
48
|
+
</div>
|
49
|
+
</div>
|
50
|
+
|
51
|
+
<br/>
|
52
|
+
|
53
|
+
|
54
|
+
<% if @specs && @specs[:locations] %>
|
55
|
+
<% @specs[:locations].each do |filename, spec| %>
|
56
|
+
|
57
|
+
<h3><%= filename %></h3>
|
58
|
+
<br/>
|
59
|
+
<div class="Box flex-auto">
|
60
|
+
<div class="Box-header Box-header--gray d-flex">
|
61
|
+
<div class="flex-auto col-md-2" role="gridcell"><b>Name</b></div>
|
62
|
+
<div class="flex-auto col-md-2" role="gridcell"><b>Required</b></div>
|
63
|
+
<div class="flex-auto col-md-2" role="gridcell"><b>Latest</b></div>
|
64
|
+
<div class="flex-auto col-md-2" role="gridcell"><b>Status</b></div>
|
65
|
+
</div>
|
66
|
+
<% spec.each do |type, dependencies| %>
|
67
|
+
<% next if dependencies.empty? %>
|
68
|
+
<% dependencies.each do |dependency| %>
|
69
|
+
<div class="Box-row Box-row--hover-gray d-flex" role="row">
|
70
|
+
<div class="flex-auto col-md-2" role="gridcell"><a href="<%= dependency[:url] %>"><%= dependency[:name] %></a></div>
|
71
|
+
<div class="flex-auto col-md-2" role="gridcell"><%= dependency[:required] %></div>
|
72
|
+
<div class="flex-auto col-md-2" role="gridcell"><%= dependency[:latest] %></div>
|
73
|
+
<div class="flex-auto col-md-2" role="gridcell"><span class="Label Label--<%= @colors.fetch(type, 'gray') %>"><%= type.to_s.split('_').collect(&:capitalize).join(' ') %></span></div>
|
74
|
+
</div>
|
75
|
+
<% end %>
|
76
|
+
<% end %>
|
77
|
+
</div>
|
78
|
+
<br/>
|
79
|
+
<% end %>
|
80
|
+
<% else %>
|
81
|
+
<div class="Box border-dashed p-2 text text-gray text-center f-4">
|
82
|
+
Nothing to see here at the moment.
|
83
|
+
</div>
|
84
|
+
<% end %>
|
85
|
+
<%= erb :_footer %>
|
86
|
+
</div>
|
87
|
+
|
88
|
+
|
89
|
+
<script src="/javascript/clipboard.min.js"></script>
|
90
|
+
<script>
|
91
|
+
new ClipboardJS('.clipboard');
|
92
|
+
function closeDropdown() {
|
93
|
+
|
94
|
+
}
|
95
|
+
</script>
|
96
|
+
<script async defer src="https://buttons.github.io/buttons.js"></script>
|
97
|
+
|
98
|
+
|
99
|
+
</body>
|
100
|
+
</html>
|
101
|
+
|
@@ -0,0 +1,163 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta name="viewport" content="width=device-width">
|
5
|
+
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
6
|
+
<title>CuttingEdge Dependency Title</title>
|
7
|
+
<style>
|
8
|
+
/* -------------------------------------
|
9
|
+
This template is thanks to: https://github.com/leemunroe/responsive-html-email-template (MIT License)
|
10
|
+
------------------------------------- */
|
11
|
+
|
12
|
+
/* -------------------------------------
|
13
|
+
INLINED WITH htmlemail.io/inline
|
14
|
+
------------------------------------- */
|
15
|
+
/* -------------------------------------
|
16
|
+
RESPONSIVE AND MOBILE FRIENDLY STYLES
|
17
|
+
------------------------------------- */
|
18
|
+
|
19
|
+
@media only screen and (max-width: 620px) {
|
20
|
+
table[class=body] h1 {
|
21
|
+
font-size: 28px !important;
|
22
|
+
margin-bottom: 10px !important;
|
23
|
+
}
|
24
|
+
table[class=body] p,
|
25
|
+
table[class=body] ul,
|
26
|
+
table[class=body] ol,
|
27
|
+
table[class=body] td,
|
28
|
+
table[class=body] span,
|
29
|
+
table[class=body] a {
|
30
|
+
font-size: 16px !important;
|
31
|
+
}
|
32
|
+
table[class=body] .wrapper,
|
33
|
+
table[class=body] .article {
|
34
|
+
padding: 10px !important;
|
35
|
+
}
|
36
|
+
table[class=body] .content {
|
37
|
+
padding: 0 !important;
|
38
|
+
}
|
39
|
+
table[class=body] .container {
|
40
|
+
padding: 0 !important;
|
41
|
+
width: 100% !important;
|
42
|
+
}
|
43
|
+
table[class=body] .main {
|
44
|
+
border-left-width: 0 !important;
|
45
|
+
border-radius: 0 !important;
|
46
|
+
border-right-width: 0 !important;
|
47
|
+
}
|
48
|
+
table[class=body] .btn table {
|
49
|
+
width: 100% !important;
|
50
|
+
}
|
51
|
+
table[class=body] .btn a {
|
52
|
+
width: 100% !important;
|
53
|
+
}
|
54
|
+
table[class=body] .img-responsive {
|
55
|
+
height: auto !important;
|
56
|
+
max-width: 100% !important;
|
57
|
+
width: auto !important;
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
/* -------------------------------------
|
62
|
+
PRESERVE THESE STYLES IN THE HEAD
|
63
|
+
------------------------------------- */
|
64
|
+
@media all {
|
65
|
+
.ExternalClass {
|
66
|
+
width: 100%;
|
67
|
+
}
|
68
|
+
.ExternalClass,
|
69
|
+
.ExternalClass p,
|
70
|
+
.ExternalClass span,
|
71
|
+
.ExternalClass font,
|
72
|
+
.ExternalClass td,
|
73
|
+
.ExternalClass div {
|
74
|
+
line-height: 100%;
|
75
|
+
}
|
76
|
+
.apple-link a {
|
77
|
+
color: inherit !important;
|
78
|
+
font-family: inherit !important;
|
79
|
+
font-size: inherit !important;
|
80
|
+
font-weight: inherit !important;
|
81
|
+
line-height: inherit !important;
|
82
|
+
text-decoration: none !important;
|
83
|
+
}
|
84
|
+
#MessageViewBody a {
|
85
|
+
color: inherit;
|
86
|
+
text-decoration: none;
|
87
|
+
font-size: inherit;
|
88
|
+
font-family: inherit;
|
89
|
+
font-weight: inherit;
|
90
|
+
line-height: inherit;
|
91
|
+
}
|
92
|
+
|
93
|
+
.btn-primary table td:hover {
|
94
|
+
background-color: #34495e !important;
|
95
|
+
}
|
96
|
+
.btn-primary a:hover {
|
97
|
+
background-color: #34495e !important;
|
98
|
+
border-color: #34495e !important;
|
99
|
+
}
|
100
|
+
}
|
101
|
+
</style>
|
102
|
+
</head>
|
103
|
+
<body class="" style="background-color: #f6f6f6; font-family: sans-serif; -webkit-font-smoothing: antialiased; font-size: 14px; line-height: 1.4; margin: 0; padding: 0; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;">
|
104
|
+
<span class="preheader" style="color: transparent; display: none; height: 0; max-height: 0; max-width: 0; opacity: 0; overflow: hidden; mso-hide: all; visibility: hidden; width: 0;">This is preheader text. Some clients will show this text as a preview.</span>
|
105
|
+
<table border="0" cellpadding="0" cellspacing="0" class="body" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background-color: #f6f6f6;">
|
106
|
+
<tr>
|
107
|
+
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;"> </td>
|
108
|
+
<td class="container" style="font-family: sans-serif; font-size: 14px; vertical-align: top; display: block; Margin: 0 auto; max-width: 580px; padding: 10px; width: 580px;">
|
109
|
+
<div class="content" style="box-sizing: border-box; display: block; Margin: 0 auto; max-width: 580px; padding: 10px;">
|
110
|
+
|
111
|
+
<!-- START CENTERED WHITE CONTAINER -->
|
112
|
+
<table class="main" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background: #ffffff; border-radius: 3px;">
|
113
|
+
|
114
|
+
<!-- START MAIN CONTENT AREA -->
|
115
|
+
<tr>
|
116
|
+
<td class="wrapper" style="font-family: sans-serif; font-size: 14px; vertical-align: top; box-sizing: border-box; padding: 20px;">
|
117
|
+
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;">
|
118
|
+
<tr>
|
119
|
+
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;">
|
120
|
+
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; Margin-bottom: 15px;">
|
121
|
+
Hi there,
|
122
|
+
</p>
|
123
|
+
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; Margin-bottom: 15px;">
|
124
|
+
This is <a href="<%= url %>">CuttingEdge</a> informing you that the dependency status for <a href="<%= "#{url}/#{project}/info" %>"><%= project %></a> has changed.
|
125
|
+
</p>
|
126
|
+
<% specs[:locations].each do |filename, spec| %>
|
127
|
+
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; Margin-bottom: 15px;">
|
128
|
+
In <b><%= filename %></b>:
|
129
|
+
<% spec.each do |type, dependencies|
|
130
|
+
next if dependencies.empty?
|
131
|
+
%>
|
132
|
+
<ul>
|
133
|
+
<b><%= type.to_s.split('_').collect(&:capitalize).join(' ') %></b>:
|
134
|
+
<ul>
|
135
|
+
<% dependencies.each do |dependency| %>
|
136
|
+
<li><%= dependency[:name] %> <%= dependency[:required] %> (latest: <%= dependency[:latest] %>)</li>
|
137
|
+
<% end %>
|
138
|
+
</ul>
|
139
|
+
</ul>
|
140
|
+
<% end %>
|
141
|
+
</p>
|
142
|
+
<% end %>
|
143
|
+
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; Margin-bottom: 15px;">
|
144
|
+
Have a nice day!
|
145
|
+
</p>
|
146
|
+
</td>
|
147
|
+
</tr>
|
148
|
+
</table>
|
149
|
+
</td>
|
150
|
+
</tr>
|
151
|
+
|
152
|
+
<!-- END MAIN CONTENT AREA -->
|
153
|
+
</table>
|
154
|
+
|
155
|
+
|
156
|
+
<!-- END CENTERED WHITE CONTAINER -->
|
157
|
+
</div>
|
158
|
+
</td>
|
159
|
+
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;"> </td>
|
160
|
+
</tr>
|
161
|
+
</table>
|
162
|
+
</body>
|
163
|
+
</html>
|
@@ -1,22 +1,44 @@
|
|
1
|
-
require File.expand_path('../../badge.rb', __FILE__)
|
2
1
|
require File.expand_path('../helpers.rb', __FILE__)
|
3
2
|
|
3
|
+
module CuttingEdge
|
4
|
+
BADGE_TEMPLATE = File.read(File.expand_path('../../templates/badge.svg.erb', __FILE__)) unless defined?(BADGE_TEMPLATE)
|
5
|
+
BADGE_OK = File.read(File.expand_path('../../public/images/ok.svg', __FILE__)) unless defined?(BADGE_OK)
|
6
|
+
BADGE_ERROR = File.read(File.expand_path('../../public/images/error.svg', __FILE__)) unless defined?(BADGE_ERROR)
|
7
|
+
BADGE_BASE_WIDTH = 25 unless defined?(BADGE_BASE_WIDTH)
|
8
|
+
BADGE_CELL_WIDTH = 25 unless defined?(BADGE_CELL_WIDTH)
|
9
|
+
BADGE_COLORS = {
|
10
|
+
ok: '#4c1',
|
11
|
+
outdated_patch: '#dfb317',
|
12
|
+
outdated_minor: '#fe7d37',
|
13
|
+
outdated_major: '#e05d44',
|
14
|
+
unknown: '#9f9f9f'
|
15
|
+
} unless defined?(BADGE_COLORS)
|
16
|
+
BADGE_LAYOUT = [:ok, :outdated_patch, :outdated_minor, :outdated_major, :unknown] unless defined?(BADGE_LAYOUT)
|
17
|
+
end
|
18
|
+
|
4
19
|
class BadgeWorker < GenericWorker
|
5
20
|
|
6
21
|
def perform(identifier)
|
7
22
|
log_info 'Running Worker!'
|
8
23
|
dependencies = get_from_store(identifier)
|
9
|
-
if dependencies
|
10
|
-
|
11
|
-
|
24
|
+
if dependencies && !dependencies.empty? && !(dependencies[:outdated] == :unknown)
|
25
|
+
result = if dependencies[:outdated] == :up_to_date
|
26
|
+
CuttingEdge::BADGE_OK
|
27
|
+
else
|
28
|
+
dependencies = ::CuttingEdge::BADGE_LAYOUT.map { |k| [k, dependencies[k]] }.to_h.
|
29
|
+
delete_if {|_, number| number == 0}
|
30
|
+
ERB.new(CuttingEdge::BADGE_TEMPLATE).result_with_hash(
|
31
|
+
base_width: CuttingEdge::BADGE_BASE_WIDTH,
|
32
|
+
cell_width: CuttingEdge::BADGE_CELL_WIDTH,
|
33
|
+
colors: CuttingEdge::BADGE_COLORS,
|
34
|
+
dependencies: dependencies
|
35
|
+
)
|
36
|
+
end
|
37
|
+
else
|
38
|
+
result = CuttingEdge::BADGE_ERROR
|
12
39
|
end
|
40
|
+
|
41
|
+
add_to_store("svg-#{identifier}", result)
|
13
42
|
GC.start
|
14
43
|
end
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
def generate_status(status)
|
19
|
-
# status is more specific than Badge.build_badge currently expects, so make it a bit less so
|
20
|
-
status == :up_to_date ? status : :out_of_date
|
21
|
-
end
|
22
44
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'http'
|
3
|
-
require 'moneta'
|
4
3
|
require File.expand_path('../../versions.rb', __FILE__)
|
5
4
|
require File.expand_path('../../langs.rb', __FILE__)
|
6
5
|
require File.expand_path('../helpers.rb', __FILE__)
|
@@ -10,18 +9,30 @@ class DependencyWorker < GenericWorker
|
|
10
9
|
|
11
10
|
# Order is significant for purposes of calculating results[:outdated]
|
12
11
|
STATUS_TYPES = [:outdated_major, :outdated_minor, :outdated_patch, :ok, :no_requirement, :unknown]
|
13
|
-
OUTDATED_TYPES = STATUS_TYPES[0..-
|
12
|
+
OUTDATED_TYPES = STATUS_TYPES[0..-4] # Which types indicate an outdated dependency. Used to calculate the total number of out-of-date dependencies.
|
14
13
|
|
15
|
-
def perform(identifier, lang, locations, dependency_types)
|
14
|
+
def perform(identifier, lang, locations, dependency_types, to_addr, auth_token = nil)
|
16
15
|
log_info 'Running Worker!'
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
16
|
+
@lang = get_lang(lang)
|
17
|
+
@provider = get_provider(identifier)
|
18
|
+
@auth_token = auth_token
|
19
|
+
old_dependencies = get_from_store(identifier)
|
20
|
+
begin
|
21
|
+
dependencies = {:locations => {}}
|
22
|
+
locations.each do |name, url|
|
23
|
+
contents = http_get(url)
|
24
|
+
dependencies[:locations][name] = get_results(@lang.parse_file(name, contents), dependency_types)
|
25
|
+
end
|
26
|
+
dependencies.merge!(generate_stats(dependencies[:locations]))
|
27
|
+
@nothing_changed = dependencies == old_dependencies
|
28
|
+
add_to_store(identifier, dependencies) unless @nothing_changed
|
29
|
+
ensure
|
30
|
+
unless @nothing_changed
|
31
|
+
badge_worker(identifier)
|
32
|
+
mail_worker(identifier, to_addr) if to_addr
|
33
|
+
end
|
34
|
+
GC.start
|
21
35
|
end
|
22
|
-
dependencies.merge!(generate_stats(dependencies))
|
23
|
-
add_to_store(identifier, dependencies)
|
24
|
-
GC.start
|
25
36
|
end
|
26
37
|
|
27
38
|
private
|
@@ -53,7 +64,7 @@ class DependencyWorker < GenericWorker
|
|
53
64
|
STATUS_TYPES.each do |type|
|
54
65
|
num = stats(type, locations)
|
55
66
|
results[type] = num
|
56
|
-
if
|
67
|
+
if outdated_type?(type)
|
57
68
|
results[:outdated_total] = results[:outdated_total].to_i + num
|
58
69
|
results[:outdated] = type unless results[:outdated] || num == 0
|
59
70
|
end
|
@@ -62,7 +73,8 @@ class DependencyWorker < GenericWorker
|
|
62
73
|
results[:outdated] = :up_to_date unless results[:outdated]
|
63
74
|
results
|
64
75
|
end
|
65
|
-
|
76
|
+
|
77
|
+
# Add up the number of dependencies of type `stat` (e.g. :ok) in the different locations where dependencies are stored.
|
66
78
|
def stats(stat, locations)
|
67
79
|
sum = 0
|
68
80
|
locations.each do |name, dependencies|
|
@@ -76,25 +88,33 @@ class DependencyWorker < GenericWorker
|
|
76
88
|
:name => name,
|
77
89
|
:required => requirement,
|
78
90
|
:latest => latest,
|
79
|
-
:type => type
|
91
|
+
:type => type,
|
92
|
+
:url => requirement == 'unknown' ? nil : @lang.website(name)
|
80
93
|
}
|
81
94
|
end
|
82
95
|
|
83
96
|
def get_lang(lang)
|
84
97
|
Object.const_get("#{lang.capitalize}Lang")
|
85
98
|
end
|
99
|
+
|
100
|
+
def get_provider(identifier)
|
101
|
+
::CuttingEdge.const_get("#{identifier.split('/').first.capitalize}Repository")
|
102
|
+
end
|
86
103
|
|
87
104
|
def http_get(url)
|
88
105
|
begin
|
89
|
-
response = HTTP.get(url)
|
106
|
+
response = HTTP.headers(@provider.headers(@auth_token)).get(url)
|
90
107
|
response.status == 200 ? response.to_s : nil
|
91
108
|
rescue HTTP::TimeoutError => e
|
92
|
-
log_info("Encountered error when fetching latest version of #{
|
109
|
+
log_info("Encountered error when fetching latest version of #{url}: #{e.class} #{e.message}")
|
93
110
|
end
|
94
111
|
end
|
95
112
|
|
96
113
|
def is_outdated?(dependency, latest_version)
|
97
114
|
!dependency.requirement.satisfied_by?(latest_version)
|
98
115
|
end
|
99
|
-
|
116
|
+
|
117
|
+
def outdated_type?(type)
|
118
|
+
OUTDATED_TYPES.include?(type)
|
119
|
+
end
|
100
120
|
end
|