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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a88b54c1fd3c4e74850a4ff3f69b4cf824883469
4
- data.tar.gz: 64edee0e7aba369d5c373809ef093d33e1d697bd
3
+ metadata.gz: 3e0e83b31e07397d043d8bc055544180d39dc6e1
4
+ data.tar.gz: 547d4937ca6744f1c1dab83b34e9ab92eb3a859d
5
5
  SHA512:
6
- metadata.gz: 5937815b3152d1f6004aa4e0412966ea93382077017701b014e993b706dac9dbb7d2e8c3bd7d76689ecade4ad6b569a1d970e7a6d1ac92793c927087f62b5656
7
- data.tar.gz: 2b140d9188a4b8684ec705e323441fbc90f7c61e2e4022dbaed647305efd98723f18e4c080941008b69194c1205d99b0a8f2e12c306cd8c0b32163a9a3efc7d6
6
+ metadata.gz: 5f6dd2a31965ba486962830447618bf8243b5e3602e072c9a966778906ae0fe9b9d3a8839d6419f455b7b87a527ff7ce0f8e582372bc68f084805aa4fde53351
7
+ data.tar.gz: 920b4da60d5eb01854bbc03d41e3c01eeaaaecd33650553629098cf8b04b6a3c072a2ee6c5251f750bc4a2592436ec2e9744a3041c913358dea85c576d1284b7
data/.gitignore CHANGED
@@ -7,4 +7,4 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
- .ruby-version
10
+ .ruby-version
@@ -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
@@ -0,0 +1,6 @@
1
+ # Changelog
2
+
3
+ # 1.0.0
4
+
5
+ - Change command line interface. The --notifier option was removed and now it is a mandatory first argument.
6
+ - Add mailgun notifier.
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
- ### Hipchat
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 --notifier hipchat --url https://url-from-hipchat
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
- ### Slack
77
+ ### Outputs
30
78
 
31
- Log into slack.com, go to **Integrations** (or Configure Integrations) and add a "Incoming WebHooks"
79
+ On Hipchat, the output will be like this:
32
80
 
33
- $ gemometer --notifier slack --url https://url-from-slack
81
+ ![Hiptchat output](/uploads/cc0861088255f9ee50c96e2c5a580271/gemometer-hipcaht.png)
34
82
 
35
83
  ## Development
36
84
 
@@ -4,4 +4,4 @@ lib = File.expand_path('../../lib', __FILE__)
4
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
  require 'gemometer/cli'
6
6
 
7
- Gemometer::CLI.start(ARGV)
7
+ Gemometer::CLI.start(ARGV)
@@ -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://github.com/hugomaiavieira/gemometer"
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.add_development_dependency "bundler", "~> 1.10"
23
- spec.add_development_dependency "rake", "~> 10.0"
24
- spec.add_development_dependency "vcr", "~> 2.9"
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
@@ -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(&:downcase)
15
+ @notifiers ||= (Notifiers.constants - [:Base]).map{ |n| n.to_s.downcase }
15
16
  end
16
17
  end
@@ -5,36 +5,102 @@ require 'gemometer'
5
5
 
6
6
  module Gemometer
7
7
  class CLI
8
- NOTIFIERS = Gemometer.notifiers
9
- MANDATORY = %w[notifier url]
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
- @options = parse_args(args)
13
- notify
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 self.parse_args(args)
17
- options = OpenStruct.new
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
- opt_parser = OptionParser.new do |opts|
20
- opts.banner = 'Usage: gemometer [options]'
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') do |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
@@ -0,0 +1,7 @@
1
+ module Gemometer
2
+ class GemArray < Array
3
+ def listed
4
+ self.class.new(select(&:group))
5
+ end
6
+ end
7
+ 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 = opts[:gems]
13
- @url = opts[: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
- uri = URI(url)
24
+ def self.mandatory_options
25
+ raise NotImplementedError
26
+ end
20
27
 
21
- http = Net::HTTP.new(uri.host, uri.port)
22
- http.use_ssl = (uri.scheme == "https")
28
+ private
23
29
 
24
- req = Net::HTTP::Post.new(uri)
25
- req.content_type = 'application/json'
30
+ def make_request
31
+ setup_auth
32
+ setup_data
33
+ http.request(request)
34
+ end
26
35
 
27
- res = http.request(req, JSON.generate(data))
36
+ def setup_auth
37
+ request.basic_auth(username, key) if require_auth?
38
+ end
28
39
 
29
- %w(204 200).include?(res.code) ||
30
- raise(Gemometer::NotifyError.new("#{res.code}: #{res.message}"))
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
- private
49
+ def uri
50
+ @uri ||= URI(url)
51
+ end
34
52
 
35
- def data
36
- raise NotImplementedError
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
- html = '<p>Outdated gems:</p><ul>'
7
- gems.each do |g|
8
- html += "<li><a href='https://rubygems.org/gems/#{g[:name]}'>#{g[:name]}</a> (newest #{g[:newest]}, installed #{g[:installed]}"
9
- html += g[:requested] ? ", requested: #{g[:requested]})" : ")"
10
- html += " in group \"#{g[:group]}\"" if g[:group]
11
- html += "</li>"
12
- end
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
- def data
19
- { message: message }
20
- end
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
- html = "Outdated gems:\n"
14
- gems.each do |g|
15
- html += "\n <https://rubygems.org/gems/#{g[:name]}|#{g[:name]}> (newest #{g[:newest]}, installed #{g[:installed]}"
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
- def data
25
- {
26
- text: message,
27
- channel: channel,
28
- username: 'Gemometer'
29
- # icon_url: "https://TODO:add-icon.png"
30
- }.reject{ |k,v| v.nil? }
31
- end
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
@@ -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 << { name: a, newest: b, installed: c, requested: d, group: e }
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
@@ -1,3 +1,3 @@
1
1
  module Gemometer
2
- VERSION = "0.1.1"
2
+ VERSION = "1.0.0"
3
3
  end
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.1.1
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: 2015-10-28 00:00:00.000000000 Z
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: :development
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: '10.0'
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: '10.0'
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: '2.9'
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: '2.9'
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://github.com/hugomaiavieira/gemometer
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.4.5.1
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