gemometer 0.1.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/.gitlab-ci.yml +43 -0
- data/CHANGELOG.md +6 -0
- data/README.md +53 -5
- data/exe/gemometer +1 -1
- data/gemometer.gemspec +6 -4
- data/lib/gemometer.rb +2 -1
- data/lib/gemometer/cli.rb +81 -41
- data/lib/gemometer/gem.rb +23 -0
- data/lib/gemometer/gem_array.rb +7 -0
- data/lib/gemometer/notifiers/base.rb +53 -15
- data/lib/gemometer/notifiers/hipchat.rb +15 -12
- data/lib/gemometer/notifiers/mailgun.rb +60 -0
- data/lib/gemometer/notifiers/slack.rb +20 -16
- data/lib/gemometer/notifiers/smtp.rb +58 -0
- data/lib/gemometer/parser.rb +7 -3
- data/lib/gemometer/version.rb +1 -1
- metadata +45 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3e0e83b31e07397d043d8bc055544180d39dc6e1
|
4
|
+
data.tar.gz: 547d4937ca6744f1c1dab83b34e9ab92eb3a859d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5f6dd2a31965ba486962830447618bf8243b5e3602e072c9a966778906ae0fe9b9d3a8839d6419f455b7b87a527ff7ce0f8e582372bc68f084805aa4fde53351
|
7
|
+
data.tar.gz: 920b4da60d5eb01854bbc03d41e3c01eeaaaecd33650553629098cf8b04b6a3c072a2ee6c5251f750bc4a2592436ec2e9744a3041c913358dea85c576d1284b7
|
data/.gitignore
CHANGED
data/.gitlab-ci.yml
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# Official language image. Look for the different tagged releases at:
|
2
|
+
# https://hub.docker.com/r/library/ruby/tags/
|
3
|
+
image: "ruby:2.3"
|
4
|
+
|
5
|
+
# Cache gems in between builds
|
6
|
+
cache:
|
7
|
+
paths:
|
8
|
+
- vendor/ruby
|
9
|
+
|
10
|
+
before_script:
|
11
|
+
- ruby -v
|
12
|
+
- gem install bundler --no-ri --no-rdoc # Bundler is not installed with the image
|
13
|
+
- bundle install --jobs $(nproc) --path vendor # Install dependencies into ./vendor/ruby
|
14
|
+
|
15
|
+
rspec:
|
16
|
+
script:
|
17
|
+
- bundle exec rake
|
18
|
+
artifacts:
|
19
|
+
paths:
|
20
|
+
- coverage/
|
21
|
+
|
22
|
+
pages:
|
23
|
+
stage: deploy
|
24
|
+
dependencies:
|
25
|
+
- rspec
|
26
|
+
script:
|
27
|
+
- mv coverage/ public/
|
28
|
+
artifacts:
|
29
|
+
paths:
|
30
|
+
- public
|
31
|
+
expire_in: 30 days
|
32
|
+
only:
|
33
|
+
- master
|
34
|
+
|
35
|
+
gemometer:
|
36
|
+
stage: deploy
|
37
|
+
allow_failure: true
|
38
|
+
script:
|
39
|
+
- bundle exec gemometer mailgun -k "$MAILGUN_KEY" -d hugomaiavieira.com -t hugomaiavieira@gmail.com
|
40
|
+
- bundle exec gemometer slack -u "$SLACK_URL"
|
41
|
+
- bundle exec gemometer hipchat -u "$HIPCHAT_URL"
|
42
|
+
only:
|
43
|
+
- master
|
data/CHANGELOG.md
ADDED
data/README.md
CHANGED
@@ -2,6 +2,10 @@
|
|
2
2
|
|
3
3
|
Gemometer is intended to be used on your continuous integration server to notify when there are new versions of the gems used on your project. It is a primitive and free [Gemnasium](https://gemnasium.com).
|
4
4
|
|
5
|
+
[![build status](https://gitlab.com/hugomaiavieira/_gemometer/badges/master/build.svg)](https://gitlab.com/hugomaiavieira/_gemometer/commits/master)
|
6
|
+
[![code climate](https://codeclimate.com/github/hugomaiavieira/gemometer/badges/gpa.svg)](https://codeclimate.com/github/hugomaiavieira/gemometer)
|
7
|
+
[![coverage report](https://gitlab.com/hugomaiavieira/_gemometer/badges/master/coverage.svg)](http://hugomaiavieira.gitlab.io/_gemometer)
|
8
|
+
|
5
9
|
## Installation
|
6
10
|
|
7
11
|
Add this line to your application's Gemfile:
|
@@ -20,17 +24,61 @@ Or install it yourself as:
|
|
20
24
|
|
21
25
|
## Usage
|
22
26
|
|
23
|
-
|
27
|
+
To get the help you can do a `gemometer --help`.
|
28
|
+
|
29
|
+
### [Hipchat](https://www.hipchat.com)
|
24
30
|
|
25
31
|
Log into hipchat.com, go to **Rooms**, select the room and go to **Integrations**, then click on "Build Your Own integration".
|
26
32
|
|
27
|
-
$ gemometer
|
33
|
+
$ gemometer hipchat --url https://url-from-hipchat
|
34
|
+
|
35
|
+
### [Slack](https://slack.com)
|
36
|
+
|
37
|
+
Log into slack.com, on the "Channel settings" go to **Add an app or integration** and add a "Incoming WebHooks".
|
38
|
+
|
39
|
+
$ gemometer slack --url https://url-from-slack
|
40
|
+
|
41
|
+
### [Mailgun](https://mailgun.com)
|
42
|
+
|
43
|
+
On mailgun, your first 10,000 emails are free every month. More than enough to notify you about your outdated gems ;)
|
44
|
+
|
45
|
+
Follow the instructions to add a domain. When its state became "Active", go to the domains page ("Domains" and click on the domain name) to get the **API Key** and use like this:
|
46
|
+
|
47
|
+
$ gemometer mailgun --domain your-domain.com --key <API Key> --to some@mail.com,other@mail.com
|
48
|
+
|
49
|
+
## Examples
|
50
|
+
|
51
|
+
### Using on GitLab CI
|
52
|
+
|
53
|
+
Add needed [secret variables](http://docs.gitlab.com/ee/ci/variables/README.html#secret-variables) (Hipchat URL for example). Then, add this to your *.gitlab-ci.yml*:
|
54
|
+
|
55
|
+
``` yml
|
56
|
+
gemometer:
|
57
|
+
stage: deploy
|
58
|
+
allow_failure: true
|
59
|
+
script:
|
60
|
+
- gemometer hipchat -u "$HIPCHAT_URL"
|
61
|
+
only:
|
62
|
+
- master
|
63
|
+
```
|
64
|
+
|
65
|
+
### Using on Codeship
|
66
|
+
|
67
|
+
On Codeship, you can add this line on your test settings:
|
68
|
+
|
69
|
+
``` bash
|
70
|
+
if [[ "$CI_BRANCH" = 'master' ]]; then gemometer hipchat -u https://url-from-hipchat; else true; fi
|
71
|
+
```
|
72
|
+
|
73
|
+
This will run the gemometer only on `master` branch builds.
|
74
|
+
|
75
|
+
**Note**: The most important output of your CI should be the last one, so it's a good idea to do this before the tests commands.
|
28
76
|
|
29
|
-
###
|
77
|
+
### Outputs
|
30
78
|
|
31
|
-
|
79
|
+
On Hipchat, the output will be like this:
|
32
80
|
|
33
|
-
|
81
|
+
![Hiptchat output](/uploads/cc0861088255f9ee50c96e2c5a580271/gemometer-hipcaht.png)
|
34
82
|
|
35
83
|
## Development
|
36
84
|
|
data/exe/gemometer
CHANGED
data/gemometer.gemspec
CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
|
|
11
11
|
|
12
12
|
spec.summary = %q{Verify and notify about outdated dependencies based on project's Gemfile}
|
13
13
|
spec.description = %q{Gemometer is intended to be used on your continuous integration server to notify when there are new versions of the gems used on your project.}
|
14
|
-
spec.homepage = "https://
|
14
|
+
spec.homepage = "https://gitlab.com/hugomaiavieira/_gemometer"
|
15
15
|
spec.license = "MIT"
|
16
16
|
|
17
17
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
@@ -19,9 +19,11 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
20
|
spec.require_paths = ["lib"]
|
21
21
|
|
22
|
-
spec.
|
23
|
-
spec.add_development_dependency "rake", "~>
|
24
|
-
spec.add_development_dependency "vcr", "~>
|
22
|
+
spec.add_runtime_dependency "bundler", ">= 1.10"
|
23
|
+
spec.add_development_dependency "rake", "~> 11.0"
|
24
|
+
spec.add_development_dependency "vcr", "~> 3.0"
|
25
25
|
spec.add_development_dependency "webmock", "~> 1.22"
|
26
26
|
spec.add_development_dependency "rspec"
|
27
|
+
spec.add_development_dependency "simplecov"
|
28
|
+
spec.add_development_dependency "codeclimate-test-reporter", "~> 1.0.0"
|
27
29
|
end
|
data/lib/gemometer.rb
CHANGED
@@ -8,9 +8,10 @@ require "gemometer/parser"
|
|
8
8
|
require "gemometer/notifiers/base"
|
9
9
|
require "gemometer/notifiers/hipchat"
|
10
10
|
require "gemometer/notifiers/slack"
|
11
|
+
require "gemometer/notifiers/mailgun"
|
11
12
|
|
12
13
|
module Gemometer
|
13
14
|
def self.notifiers
|
14
|
-
(Notifiers.constants - [:Base]).map
|
15
|
+
@notifiers ||= (Notifiers.constants - [:Base]).map{ |n| n.to_s.downcase }
|
15
16
|
end
|
16
17
|
end
|
data/lib/gemometer/cli.rb
CHANGED
@@ -5,36 +5,102 @@ require 'gemometer'
|
|
5
5
|
|
6
6
|
module Gemometer
|
7
7
|
class CLI
|
8
|
-
|
9
|
-
|
8
|
+
attr_reader :options, :notifier_name
|
9
|
+
|
10
|
+
def initialize(args)
|
11
|
+
@notifier_name = args.shift
|
12
|
+
@options = OpenStruct.new
|
13
|
+
parse_args(args)
|
14
|
+
end
|
10
15
|
|
11
16
|
def self.start(args)
|
12
|
-
|
13
|
-
|
17
|
+
new(args).notify
|
18
|
+
end
|
19
|
+
|
20
|
+
def notify
|
21
|
+
begin
|
22
|
+
options.gems = gems
|
23
|
+
notifier_class.new(options.to_h).notify
|
24
|
+
rescue Gemometer::NotifyError => e
|
25
|
+
abort(e.message)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def parse_args(args)
|
32
|
+
begin
|
33
|
+
opt_parser.parse!(args)
|
34
|
+
verify_mandatory_options!
|
35
|
+
rescue OptionParser::InvalidArgument, OptionParser::MissingArgument, OptionParser::InvalidOption
|
36
|
+
# Friendly output when parsing fails
|
37
|
+
abort("\n#{$!}\n\n\n#{opt_parser}")
|
38
|
+
end
|
14
39
|
end
|
15
40
|
|
16
|
-
def
|
17
|
-
|
41
|
+
def verify_mandatory_options!
|
42
|
+
missing = notifier_class.mandatory_options - options.to_h.keys
|
43
|
+
if missing.any?
|
44
|
+
abort("\nMissing options for '#{notifier_name}' notifier: #{missing.join(', ')}\n\n\n#{opt_parser}")
|
45
|
+
end
|
46
|
+
end
|
18
47
|
|
19
|
-
|
20
|
-
|
48
|
+
def gems
|
49
|
+
parser = Gemometer::Parser.new(Gemometer::System.bundle_outdated)
|
50
|
+
parser.parse
|
51
|
+
options.listed_only ? parser.gems.listed : parser.gems
|
52
|
+
end
|
53
|
+
|
54
|
+
def notifier_class
|
55
|
+
@notifier_class ||= if Gemometer.notifiers.include?(notifier_name)
|
56
|
+
Gemometer::Notifiers.const_get(notifier_name.capitalize)
|
57
|
+
else
|
58
|
+
abort("\nWrong notifier '#{notifier_name}'. Available notifiers: #{Gemometer.notifiers.join(', ')}\n\n\n#{opt_parser}")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def opt_parser
|
63
|
+
@opt_parser ||= OptionParser.new do |opts|
|
64
|
+
opts.banner = 'Usage: gemometer NOTIFIER [options]'
|
21
65
|
|
66
|
+
opts.separator ''
|
67
|
+
opts.separator "Available notifiers: #{Gemometer.notifiers.join(', ')}"
|
22
68
|
opts.separator ''
|
23
69
|
opts.separator 'Specific options:'
|
24
70
|
|
25
|
-
opts.on('-n', '--notifier NOTIFIER', NOTIFIERS, {},
|
26
|
-
'Specify the notifier app', " (#{NOTIFIERS.join(', ')})") do |notifier|
|
27
|
-
options.notifier = notifier
|
28
|
-
end
|
29
|
-
|
30
71
|
opts.on('-u', '--url URL',
|
31
|
-
'Specify the app notification url'
|
72
|
+
'Specify the app notification url',
|
73
|
+
' Mandatory for Slack and Hipchat.') do |url|
|
32
74
|
options.url = url
|
33
75
|
end
|
34
76
|
|
77
|
+
opts.on('-k', '--key API Key',
|
78
|
+
'Specify the API Key',
|
79
|
+
' Mandatory for mailgun.') do |key|
|
80
|
+
options.key = key
|
81
|
+
end
|
82
|
+
|
83
|
+
opts.on('-t', '--to EMAIL',
|
84
|
+
'Specify the email address of the recipient(s). You can use commas to separate multiple recipients.',
|
85
|
+
' Mandatory for mailgun.') do |to|
|
86
|
+
options.to = to
|
87
|
+
end
|
88
|
+
|
89
|
+
opts.on('-d', '--domain DOMAIN',
|
90
|
+
'Specify the domain configured on mailgun.',
|
91
|
+
' Mandatory for mailgun.') do |domain|
|
92
|
+
options.domain = domain
|
93
|
+
end
|
94
|
+
|
35
95
|
opts.separator ''
|
36
96
|
opts.separator 'Common options:'
|
37
97
|
|
98
|
+
opts.on('-l', '--listed-only', "Only verify gems listed directly on Gemfile (don't verify dependencies)") do
|
99
|
+
options.listed_only = true
|
100
|
+
end
|
101
|
+
|
102
|
+
opts.separator ''
|
103
|
+
|
38
104
|
opts.on_tail('-h', '--help', 'Show this message') do
|
39
105
|
puts opts
|
40
106
|
exit
|
@@ -45,32 +111,6 @@ module Gemometer
|
|
45
111
|
exit
|
46
112
|
end
|
47
113
|
end
|
48
|
-
|
49
|
-
begin
|
50
|
-
opt_parser.parse!(args)
|
51
|
-
missing = MANDATORY.select{ |param| options.send(param).nil? }
|
52
|
-
if missing.any?
|
53
|
-
abort("\nMissing options: #{missing.join(', ')}\n\n\n#{opt_parser}")
|
54
|
-
end
|
55
|
-
rescue OptionParser::InvalidArgument, OptionParser::MissingArgument, OptionParser::InvalidOption
|
56
|
-
# Friendly output when parsing fails
|
57
|
-
abort("\n#{$!}\n\n\n#{opt_parser}")
|
58
|
-
end
|
59
|
-
|
60
|
-
options
|
61
|
-
end
|
62
|
-
|
63
|
-
def self.notify
|
64
|
-
begin
|
65
|
-
gems = Gemometer::Parser.new(Gemometer::System.bundle_outdated).parse
|
66
|
-
|
67
|
-
Gemometer::Notifiers.const_get(@options.notifier.capitalize).new(
|
68
|
-
gems: gems,
|
69
|
-
url: @options.url
|
70
|
-
).notify
|
71
|
-
rescue Gemometer::NotifyError => e
|
72
|
-
abort(e.message)
|
73
|
-
end
|
74
114
|
end
|
75
115
|
end
|
76
|
-
end
|
116
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Gemometer
|
2
|
+
class Gem
|
3
|
+
attr_reader :name, :newest, :installed, :requested, :group
|
4
|
+
|
5
|
+
def initialize(attrs)
|
6
|
+
attrs.each { |key, value| instance_variable_set("@#{key}", value) }
|
7
|
+
end
|
8
|
+
|
9
|
+
def message_line
|
10
|
+
"(newest #{newest}, installed #{installed}#{requested_msg})#{group_msg}"
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def requested_msg
|
16
|
+
requested ? ", requested: #{requested}" : ""
|
17
|
+
end
|
18
|
+
|
19
|
+
def group_msg
|
20
|
+
group ? " in group \"#{group}\"" : ""
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -6,35 +6,73 @@ require 'gemometer/errors'
|
|
6
6
|
module Gemometer
|
7
7
|
module Notifiers
|
8
8
|
class Base
|
9
|
-
attr_reader :gems, :url
|
9
|
+
attr_reader :gems, :url, :key, :username
|
10
10
|
|
11
11
|
def initialize(opts)
|
12
|
-
@gems
|
13
|
-
@url
|
12
|
+
@gems = opts[:gems]
|
13
|
+
@url = opts[:url]
|
14
|
+
@key = opts[:key]
|
15
|
+
@username = opts[:username]
|
14
16
|
end
|
15
17
|
|
16
18
|
def notify
|
17
19
|
return false if gems.empty?
|
20
|
+
response = make_request
|
21
|
+
%w(204 200).include?(response.code) || raise(Gemometer::NotifyError.new("#{response.code}: #{response.message}"))
|
22
|
+
end
|
18
23
|
|
19
|
-
|
24
|
+
def self.mandatory_options
|
25
|
+
raise NotImplementedError
|
26
|
+
end
|
20
27
|
|
21
|
-
|
22
|
-
http.use_ssl = (uri.scheme == "https")
|
28
|
+
private
|
23
29
|
|
24
|
-
|
25
|
-
|
30
|
+
def make_request
|
31
|
+
setup_auth
|
32
|
+
setup_data
|
33
|
+
http.request(request)
|
34
|
+
end
|
26
35
|
|
27
|
-
|
36
|
+
def setup_auth
|
37
|
+
request.basic_auth(username, key) if require_auth?
|
38
|
+
end
|
28
39
|
|
29
|
-
|
30
|
-
|
40
|
+
def setup_data
|
41
|
+
if json?
|
42
|
+
request.content_type = 'application/json'
|
43
|
+
request.body = JSON.generate(data)
|
44
|
+
else
|
45
|
+
request.set_form_data(data)
|
46
|
+
end
|
31
47
|
end
|
32
48
|
|
33
|
-
|
49
|
+
def uri
|
50
|
+
@uri ||= URI(url)
|
51
|
+
end
|
34
52
|
|
35
|
-
|
36
|
-
|
53
|
+
def http
|
54
|
+
@http ||= begin
|
55
|
+
_http = Net::HTTP.new(uri.host, uri.port)
|
56
|
+
_http.use_ssl = (uri.scheme == "https")
|
57
|
+
_http
|
37
58
|
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def request
|
62
|
+
@request ||= Net::HTTP::Post.new(uri)
|
63
|
+
end
|
64
|
+
|
65
|
+
def data
|
66
|
+
raise NotImplementedError
|
67
|
+
end
|
68
|
+
|
69
|
+
def json?
|
70
|
+
true
|
71
|
+
end
|
72
|
+
|
73
|
+
def require_auth?
|
74
|
+
false
|
75
|
+
end
|
38
76
|
end
|
39
77
|
end
|
40
|
-
end
|
78
|
+
end
|
@@ -3,21 +3,24 @@ module Gemometer
|
|
3
3
|
module Notifiers
|
4
4
|
class Hipchat < Base
|
5
5
|
def message
|
6
|
-
|
7
|
-
gems.each
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
html += '</ul>'
|
6
|
+
msg = '<p>Outdated gems:</p><ul>'
|
7
|
+
gems.each { |g| msg += "<li>#{ruby_gems_link(g.name)} #{g.message_line}</li>" }
|
8
|
+
msg += '</ul>'
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.mandatory_options
|
12
|
+
[:url]
|
14
13
|
end
|
15
14
|
|
16
15
|
private
|
17
16
|
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
def data
|
18
|
+
{ message: message }
|
19
|
+
end
|
20
|
+
|
21
|
+
def ruby_gems_link(name)
|
22
|
+
"<a href='https://rubygems.org/gems/#{name}'>#{name}</a>"
|
23
|
+
end
|
21
24
|
end
|
22
25
|
end
|
23
|
-
end
|
26
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# https://documentation.mailgun.com/api-sending.html
|
2
|
+
module Gemometer
|
3
|
+
module Notifiers
|
4
|
+
class Mailgun < Base
|
5
|
+
attr_reader :domain, :to
|
6
|
+
|
7
|
+
def initialize(opts)
|
8
|
+
@domain = opts[:domain]
|
9
|
+
@to = opts[:to]
|
10
|
+
super(opts)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.mandatory_options
|
14
|
+
[:domain, :to, :key]
|
15
|
+
end
|
16
|
+
|
17
|
+
def message
|
18
|
+
msg = '<p>Outdated gems:</p><ul>'
|
19
|
+
gems.each { |g| msg += "<li>#{ruby_gems_link(g.name)} #{g.message_line}</li>" }
|
20
|
+
msg += '</ul>'
|
21
|
+
end
|
22
|
+
|
23
|
+
def username
|
24
|
+
'api'
|
25
|
+
end
|
26
|
+
|
27
|
+
def url
|
28
|
+
"https://api.mailgun.net/v3/#{domain}/messages"
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def data
|
34
|
+
{
|
35
|
+
from: sender,
|
36
|
+
to: to,
|
37
|
+
html: message,
|
38
|
+
subject: 'Some gems are Outdated'
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
def sender
|
43
|
+
"Gemometer <gemometer@#{domain}>"
|
44
|
+
end
|
45
|
+
|
46
|
+
def ruby_gems_link(name)
|
47
|
+
"<a href='https://rubygems.org/gems/#{name}'>#{name}</a>"
|
48
|
+
end
|
49
|
+
|
50
|
+
def json?
|
51
|
+
false
|
52
|
+
end
|
53
|
+
|
54
|
+
def require_auth?
|
55
|
+
true
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
@@ -9,26 +9,30 @@ module Gemometer
|
|
9
9
|
super(opts)
|
10
10
|
end
|
11
11
|
|
12
|
+
def self.mandatory_options
|
13
|
+
[:url]
|
14
|
+
end
|
15
|
+
|
12
16
|
def message
|
13
|
-
|
14
|
-
gems.each
|
15
|
-
|
16
|
-
html += g[:requested] ? ", requested: #{g[:requested]})" : ")"
|
17
|
-
html += " in group \"#{g[:group]}\"" if g[:group]
|
18
|
-
end
|
19
|
-
html += "\n-"
|
17
|
+
msg = "Outdated gems:\n"
|
18
|
+
gems.each { |g| msg += "\n #{ruby_gems_link(g.name)} #{g.message_line}" }
|
19
|
+
msg += "\n-"
|
20
20
|
end
|
21
21
|
|
22
22
|
private
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
24
|
+
def data
|
25
|
+
{
|
26
|
+
text: message,
|
27
|
+
channel: channel,
|
28
|
+
username: 'Gemometer'
|
29
|
+
# icon_url: "https://TODO:add-icon.png"
|
30
|
+
}.reject{ |_, v| v.nil? }
|
31
|
+
end
|
32
|
+
|
33
|
+
def ruby_gems_link(name)
|
34
|
+
"<https://rubygems.org/gems/#{name}|#{name}>"
|
32
35
|
end
|
36
|
+
end
|
33
37
|
end
|
34
|
-
end
|
38
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'net/smtp'
|
2
|
+
|
3
|
+
module Gemometer
|
4
|
+
module Notifiers
|
5
|
+
class Smtp
|
6
|
+
attr_reader :gems, :to, :sender, :server, :port, :domain, :username, :password, :scheme
|
7
|
+
|
8
|
+
def initialize(opts)
|
9
|
+
@gems = opts[:gems]
|
10
|
+
@to = opts[:to]
|
11
|
+
@sender = ENV['SMTP_SENDER']
|
12
|
+
@server = ENV['SMTP_SERVER']
|
13
|
+
@port = ENV['SMTP_PORT'] || SMTP.default_port
|
14
|
+
@domain = ENV['SMTP_DOMAIN']
|
15
|
+
@username = ENV['SMTP_USERNAME']
|
16
|
+
@password = ENV['SMTP_PASSWORD']
|
17
|
+
@scheme = ENV['SMTP_AUTH_SCHEME'] || :plain # :plain, :login, or :cram_md5
|
18
|
+
end
|
19
|
+
|
20
|
+
def notify
|
21
|
+
|
22
|
+
Net::SMTP.start(server, port, domain, username, password, scheme) do |smtp|
|
23
|
+
smtp.send_message(message, sender, to)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def message
|
28
|
+
header + body
|
29
|
+
end
|
30
|
+
|
31
|
+
def header
|
32
|
+
%{
|
33
|
+
From: Gemometer <#{sender}>
|
34
|
+
To: #{to.join(",")}
|
35
|
+
MIME-Version: 1.0
|
36
|
+
Content-Type: text/html; charset=utf-8
|
37
|
+
Subject: Some gems are Outdated
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
def to
|
42
|
+
@to.gsub("\s", '').split(",") if @to
|
43
|
+
end
|
44
|
+
|
45
|
+
def body
|
46
|
+
msg = '<p>Outdated gems:</p><ul>'
|
47
|
+
gems.each { |g| msg += "<li>#{ruby_gems_link(g.name)} #{g.message_line}</li>" }
|
48
|
+
msg += '</ul>'
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def ruby_gems_link(name)
|
54
|
+
"<a href='https://rubygems.org/gems/#{name}'>#{name}</a>"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/lib/gemometer/parser.rb
CHANGED
@@ -1,19 +1,23 @@
|
|
1
|
+
require_relative './gem_array'
|
2
|
+
require_relative './gem'
|
3
|
+
|
1
4
|
module Gemometer
|
2
5
|
class Parser
|
3
6
|
REGEX=%r(\* ([^\s]+) \(newest ([0-9|\.]+), installed ([0-9|\.]+)[\)|,](?: requested (.*[0-9|\.]+)\) in group "(\w+)")?)
|
4
7
|
|
8
|
+
attr_reader :gems
|
9
|
+
|
5
10
|
def initialize(str)
|
6
11
|
@str = str
|
7
|
-
@gems =
|
12
|
+
@gems = GemArray.new
|
8
13
|
end
|
9
14
|
|
10
15
|
def parse
|
11
16
|
if @gems.empty?
|
12
17
|
@str.scan(REGEX) do |a, b, c, d, e|
|
13
|
-
@gems <<
|
18
|
+
@gems << Gem.new(name: a, newest: b, installed: c, requested: d, group: e)
|
14
19
|
end
|
15
20
|
end
|
16
|
-
@gems
|
17
21
|
end
|
18
22
|
end
|
19
23
|
end
|
data/lib/gemometer/version.rb
CHANGED
metadata
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gemometer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hugo Maia Vieira
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-01-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.10'
|
20
|
-
type: :
|
20
|
+
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.10'
|
27
27
|
- !ruby/object:Gem::Dependency
|
@@ -30,28 +30,28 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '11.0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '11.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: vcr
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '3.0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '3.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: webmock
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,6 +80,34 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: simplecov
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: codeclimate-test-reporter
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 1.0.0
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 1.0.0
|
83
111
|
description: Gemometer is intended to be used on your continuous integration server
|
84
112
|
to notify when there are new versions of the gems used on your project.
|
85
113
|
email:
|
@@ -90,8 +118,10 @@ extensions: []
|
|
90
118
|
extra_rdoc_files: []
|
91
119
|
files:
|
92
120
|
- ".gitignore"
|
121
|
+
- ".gitlab-ci.yml"
|
93
122
|
- ".rspec"
|
94
123
|
- ".travis.yml"
|
124
|
+
- CHANGELOG.md
|
95
125
|
- CODE_OF_CONDUCT.md
|
96
126
|
- Gemfile
|
97
127
|
- LICENSE.txt
|
@@ -104,13 +134,17 @@ files:
|
|
104
134
|
- lib/gemometer.rb
|
105
135
|
- lib/gemometer/cli.rb
|
106
136
|
- lib/gemometer/errors.rb
|
137
|
+
- lib/gemometer/gem.rb
|
138
|
+
- lib/gemometer/gem_array.rb
|
107
139
|
- lib/gemometer/notifiers/base.rb
|
108
140
|
- lib/gemometer/notifiers/hipchat.rb
|
141
|
+
- lib/gemometer/notifiers/mailgun.rb
|
109
142
|
- lib/gemometer/notifiers/slack.rb
|
143
|
+
- lib/gemometer/notifiers/smtp.rb
|
110
144
|
- lib/gemometer/parser.rb
|
111
145
|
- lib/gemometer/system.rb
|
112
146
|
- lib/gemometer/version.rb
|
113
|
-
homepage: https://
|
147
|
+
homepage: https://gitlab.com/hugomaiavieira/_gemometer
|
114
148
|
licenses:
|
115
149
|
- MIT
|
116
150
|
metadata: {}
|
@@ -130,7 +164,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
130
164
|
version: '0'
|
131
165
|
requirements: []
|
132
166
|
rubyforge_project:
|
133
|
-
rubygems_version: 2.
|
167
|
+
rubygems_version: 2.5.2
|
134
168
|
signing_key:
|
135
169
|
specification_version: 4
|
136
170
|
summary: Verify and notify about outdated dependencies based on project's Gemfile
|