gemometer 0.1.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
[](https://gitlab.com/hugomaiavieira/_gemometer/commits/master)
|
6
|
+
[](https://codeclimate.com/github/hugomaiavieira/gemometer)
|
7
|
+
[](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
|
+

|
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
|