gem_watch 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2009, Fabien Jakimowicz <fabien@jakimowicz.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
+ of the Software, and to permit persons to whom the Software is furnished to do
8
+ so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,100 @@
1
+ = GemWatch
2
+
3
+ == DESCRIPTION
4
+ GemWatch helps sysadmins to watch their systems to see if an update is available for installed gems. GemWatch can watch all installed gems or only specified gems. Results can be outputted to stdout or email(s) addresses.
5
+
6
+ A cron task launching GemWatch with a configuration file can be used to launch checks every day.
7
+
8
+ == SYNOPSIS
9
+
10
+ === Command line options
11
+ Checks options:
12
+ -u=<all|gem1, gem2, ...> Precise what are the gems to check for the update.
13
+ --check-update-on
14
+
15
+ Email options:
16
+ -e=email1, email2, ... Email address to send results.
17
+ --email-recipient
18
+ -s, --email-subject=subject Subject used in the email.
19
+ -f, --email-from=email Email's sender.
20
+
21
+ SMTP options:
22
+ --smtp-host=localhost SMTP host to connect to send emails.
23
+ --smtp-port=25 SMTP port to connect to send emails.
24
+
25
+ General options:
26
+ -c, --config=config.yml YAML configuration file. Overrides command line attributes.
27
+ -S, --stdout Display results on stdout instead of mailing them.
28
+ -h, --help Show this message
29
+
30
+ === Configuration file
31
+ A yaml configuration file can be used to specify all options:
32
+
33
+ email:
34
+ recipients: admin@example.com
35
+ subject: Critical update !
36
+
37
+ smtp:
38
+ host: 127.0.0.1
39
+ port: 25
40
+
41
+ check:
42
+ update_on: super_security, rails
43
+
44
+ === Command line examples
45
+ $> gemwatch
46
+
47
+ Those gems can be updated to their latest version:
48
+
49
+ Name Local Remote
50
+ =========================================
51
+ ZenTest 4.1.3 4.1.4
52
+ sqlite3-ruby 1.2.4 1.2.5
53
+ thor 0.9.9 0.11.5
54
+ fake_mechanize 0.0.0 0.0.1
55
+ rubyforge 1.0.3 1.0.4
56
+ net-ssh 2.0.11 2.0.13
57
+ hirb 0.2.4 0.2.5
58
+ ruby_parser 2.0.3 2.0.4
59
+ ruby2ruby 1.2.3 1.2.4
60
+ rmagick 2.10.0 2.11.0
61
+ hoe 2.3.2 2.3.3
62
+ sexp_processor 3.0.2 3.0.3
63
+ nokogiri 1.3.2 1.3.3
64
+ RubyInline 3.8.2 3.8.3
65
+
66
+ $> gemwatch --check-update-on=rails
67
+
68
+ Nothing to report.
69
+
70
+
71
+ == REQUIREMENTS
72
+
73
+ * yaml gem
74
+
75
+ == INSTALL
76
+ gem install gem_watch
77
+
78
+ == LICENSE
79
+
80
+ (The MIT License)
81
+
82
+ Copyright (c) 2009, Fabien Jakimowicz <fabien@jakimowicz.com>
83
+
84
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
85
+ this software and associated documentation files (the "Software"), to deal in
86
+ the Software without restriction, including without limitation the rights to
87
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
88
+ of the Software, and to permit persons to whom the Software is furnished to do
89
+ so, subject to the following conditions:
90
+
91
+ The above copyright notice and this permission notice shall be included in all
92
+ copies or substantial portions of the Software.
93
+
94
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
95
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
96
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
97
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
98
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
99
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
100
+ SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,61 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "gem_watch"
8
+ gem.summary = %Q{watch over outdated gems and send an email to notice admin.}
9
+ gem.description = %Q{GemWatch watches over outdated gems in your system and send an email to inform administrators about available update, like apticron on debian}
10
+ gem.email = "fabien@jakimowicz.com"
11
+ gem.homepage = "http://github.com/jakimowicz/gem_watch"
12
+ gem.authors = ["Fabien Jakimowicz"]
13
+ gem.rubyforge_project = "gemwatch"
14
+ gem.add_development_dependency "thoughtbot-shoulda"
15
+ gem.add_dependency 'yaml'
16
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
17
+ end
18
+ Jeweler::RubyforgeTasks.new do |rubyforge|
19
+ rubyforge.doc_task = "rdoc"
20
+ end
21
+ rescue LoadError
22
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
23
+ end
24
+
25
+ require 'rake/testtask'
26
+ Rake::TestTask.new(:test) do |test|
27
+ test.libs << 'lib' << 'test'
28
+ test.pattern = 'test/**/*_test.rb'
29
+ test.verbose = true
30
+ end
31
+
32
+ begin
33
+ require 'rcov/rcovtask'
34
+ Rcov::RcovTask.new do |test|
35
+ test.libs << 'test'
36
+ test.pattern = 'test/**/*_test.rb'
37
+ test.verbose = true
38
+ end
39
+ rescue LoadError
40
+ task :rcov do
41
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
42
+ end
43
+ end
44
+
45
+ task :test => :check_dependencies
46
+
47
+ task :default => :test
48
+
49
+ require 'rake/rdoctask'
50
+ Rake::RDocTask.new do |rdoc|
51
+ if File.exist?('VERSION')
52
+ version = File.read('VERSION')
53
+ else
54
+ version = ""
55
+ end
56
+
57
+ rdoc.rdoc_dir = 'rdoc'
58
+ rdoc.title = "gem_watch #{version}"
59
+ rdoc.rdoc_files.include('README*')
60
+ rdoc.rdoc_files.include('lib/**/*.rb')
61
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/bin/gemwatch ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "gem_watch/command"
4
+
5
+ GemWatch::Command.new.run ARGV
@@ -0,0 +1,34 @@
1
+ require "gem_watch"
2
+
3
+ # Implements a check which will run some tests on one or multiple gems.
4
+ # Negative results that need to be noticed are stored in the <tt>impacts</tt> hash.
5
+ # This class implements basic behavior for check, specific test implementation
6
+ # and interpretation is done in the children classes.
7
+ class GemWatch::Check
8
+ # Stores the gem name to check on
9
+ attr_reader :gem_name
10
+
11
+ # Hash to store which gem has failed check and why
12
+ attr_reader :impacts
13
+
14
+ # Take a <tt>gem_name</tt> to check.
15
+ def initialize(gem_name = :all)
16
+ @gem_name = gem_name
17
+ @impacts = {}
18
+ end
19
+
20
+ # Run check on <tt>gem_name</tt>.
21
+ def run
22
+ raise "Not implemented for this check."
23
+ end
24
+
25
+ # Returns true if test was passed, false otherwise.
26
+ def passed?
27
+ @impacts.empty?
28
+ end
29
+
30
+ # Pretty displays of results (interpretation of <tt>impacts</tt>).
31
+ def results
32
+ @impacts.inspect
33
+ end
34
+ end
@@ -0,0 +1,34 @@
1
+ require "rubygems"
2
+ require "gem_watch/check"
3
+
4
+ # Implements a simple check to assure that installed gem(s) are up to date.
5
+ class GemWatch::Check::Update < GemWatch::Check
6
+
7
+ # Check if specified gem(s) are up to date.
8
+ def run
9
+ if gem_name.to_s == 'all'
10
+ Gem::SourceIndex.from_installed_gems.outdated.each {|g| run_on g}
11
+ else
12
+ run_on gem_name
13
+ end
14
+ end
15
+
16
+ # Displays a formated result with gem name, local and remote version.
17
+ def results
18
+ @impacts.collect do |name, (local_version, remote_version)|
19
+ "%-20s%-10s%s" % [name, local_version, remote_version]
20
+ end
21
+ end
22
+
23
+ private
24
+ def run_on(gem_name)
25
+ local = Gem::SourceIndex.from_installed_gems.find_name(gem_name).last
26
+
27
+ dep = Gem::Dependency.new local.name, ">= #{local.version}"
28
+ remotes = Gem::SpecFetcher.fetcher.fetch dep
29
+ remote = remotes.last.first
30
+
31
+ @impacts[local.name] = [local.version, remote.version] if local.version != remote.version
32
+ end
33
+
34
+ end
@@ -0,0 +1,132 @@
1
+ # Pure ruby requires
2
+ require 'optparse'
3
+ require 'net/smtp'
4
+
5
+ # Gems
6
+ require 'yaml'
7
+
8
+ # Internal stuff
9
+ require "gem_watch"
10
+ require "gem_watch/command_options"
11
+
12
+ # Command implements a command to be executed based on options.
13
+ # It is directly used by the command line interface.
14
+ class GemWatch::Command
15
+ def initialize
16
+ @options = GemWatch::CommandOptions.new
17
+ end
18
+
19
+ # Run the command based on default options and given <tt>args</tt>.
20
+ def run(args = {})
21
+ parse_options args
22
+ gw = GemWatch.new(:update => @options.check_update_on)
23
+ gw.run_checks
24
+ if gw.passed?
25
+ say "Nothing to report."
26
+ else
27
+ say gw.results
28
+ end
29
+ end
30
+
31
+ protected
32
+ # Based on options, display given <tt>str</tt> to stdout or to mail.
33
+ def say(str)
34
+ if @options.stdout or @options.email_recipients.empty?
35
+ puts str
36
+ else
37
+ send_email str
38
+ end
39
+ end
40
+
41
+ # Send an email with given <tt>message</tt>.
42
+ def send_email(message)
43
+ email = <<-END_OF_MESSAGE
44
+ From: GemWatch <#{@options.email_from}>
45
+ To: %s
46
+ Subject: #{@options.email_subject}
47
+
48
+ #{message}
49
+ END_OF_MESSAGE
50
+
51
+ Net::SMTP.start(@options.smtp_host, @options.smtp_port) do |smtp|
52
+ @options.email_recipients.each do |recipient|
53
+ smtp.send_message email % recipient, @options.email_from, recipient
54
+ end
55
+ end
56
+ end
57
+
58
+ # Parse given <tt>args</tt> with OptionParser to generate options.
59
+ def parse_options(args)
60
+ OptionParser.new do |opts|
61
+ opts.banner = "Usage: gemwatch [options]"
62
+
63
+ opts.separator ""
64
+ opts.separator "Checks options:"
65
+
66
+ opts.on "-u", "--check-update-on=<all|gem1, gem2, ...>", "Precise what are the gems to check for the update." do |gems|
67
+ @options.check_update_on = gems
68
+ end
69
+
70
+ opts.separator ""
71
+ opts.separator "Email options:"
72
+
73
+ opts.on "-e", "--email-recipient=email1, email2, ...", "Email address to send results." do |email|
74
+ @options.email_recipients = email
75
+ @options.stdout = false
76
+ end
77
+
78
+ opts.on "-s", "--email-subject=subject", "Subject used in the email." do |subject|
79
+ @options.email_subject = subject
80
+ end
81
+
82
+ opts.on "-f", "--email-from=email", "Email's sender." do |email|
83
+ @options.email_recipient = email.split(',').collect {|email| email.strip}
84
+ @options.stdout = false
85
+ end
86
+
87
+ opts.separator ""
88
+ opts.separator "SMTP options:"
89
+
90
+ opts.on "--smtp-host=localhost", "SMTP host to connect to send emails." do |host|
91
+ @options.smtp_host = host
92
+ end
93
+
94
+ opts.on "--smtp-port=25", "SMTP port to connect to send emails." do |port|
95
+ @options.smtp_port = port
96
+ end
97
+
98
+ opts.separator ""
99
+ opts.separator "General options:"
100
+
101
+ opts.on "-c", "--config=config.yml", "YAML configuration file. Overrides command line attributes." do |config_file|
102
+ y = YAML.parse_file(config_file)
103
+ GemWatch::CommandOptions::Defaults.each_key do |key|
104
+ value = yaml_value(y, key.to_s)
105
+ @options.send("#{key}=", value) if value
106
+ end
107
+ end
108
+
109
+ opts.on "-S", "--stdout", "Display results on stdout instead of mailing them." do
110
+ @options.stdout = true
111
+ end
112
+
113
+ opts.on_tail "-h", "--help", "Show this message" do
114
+ puts opts
115
+ exit
116
+ end
117
+
118
+ opts.parse!(args)
119
+ end
120
+ end
121
+
122
+ # Given a <tt>yaml</tt> object and a <tt>key</tt> string, returns the value.
123
+ # If <tt>key</tt> contains an underscore character, it will consider each word between underscores as a subtree.
124
+ def yaml_value(yaml, key)
125
+ if key.include?('_')
126
+ first_key, sep, rest = key.partition('_')
127
+ yaml_value yaml[first_key], rest
128
+ else
129
+ yaml[key].value rescue nil
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,45 @@
1
+ require "gem_watch"
2
+
3
+ # Command options class for the command line interface. It is initialized with Defaults values.
4
+ class GemWatch::CommandOptions
5
+ attr_accessor :smtp_host
6
+ attr_accessor :smtp_port
7
+
8
+ attr_accessor :email_recipients
9
+ attr_accessor :email_subject
10
+ attr_accessor :email_from
11
+
12
+ attr_accessor :stdout
13
+ attr_accessor :check_update_on
14
+
15
+ # Defaults values for command line interface.
16
+ Defaults = {
17
+ # SMTP Part
18
+ :smtp_host => 'localhost',
19
+ :smtp_port => 25,
20
+ # Email part
21
+ :email_recipients => [],
22
+ :email_subject => "GemWatch has found something to report",
23
+ :email_from => "gemwatch@example.com",
24
+ # Checks part
25
+ :check_update_on => :all,
26
+ # General part
27
+ :stdout => true
28
+ }
29
+
30
+ # Initialize a new object with Defaults values.
31
+ def initialize
32
+ Defaults.each {|key, value| send "#{key}=", value}
33
+ end
34
+
35
+ # Overrides the default attr_accessor to split a string of multiple email addresses in a array.
36
+ def email_recipients=(recipients)
37
+ @email_recipients = case recipients.class.name
38
+ when 'Array'
39
+ recipients
40
+ when 'String'
41
+ recipients.split(',').collect {|email| email.strip}
42
+ end
43
+ @stdout = @email_recipients.empty?
44
+ end
45
+ end
data/lib/gem_watch.rb ADDED
@@ -0,0 +1,48 @@
1
+ # GemWatch regroups multiple checks and consolidates them in a pretty formated result.
2
+ class GemWatch
3
+ # Update object to perform check on
4
+ attr_reader :update_on
5
+
6
+ # Initialize a new GemWatch object using <tt>params</tt>.
7
+ # == params
8
+ # <tt>:update</tt>: accepts a String of coma separated gem names or directly an Array of gem string names.
9
+ def initialize(params = {})
10
+ @update_on = case params[:update].class
11
+ when Array
12
+ params[:update]
13
+ when String
14
+ params[:update].split(',').collect {|s| s.strip}
15
+ else
16
+ [params[:update]]
17
+ end
18
+
19
+ @update_on = @update_on.collect {|name| GemWatch::Check::Update.new name}
20
+ end
21
+
22
+ # Run all checks
23
+ def run_checks
24
+ @update_on.each {|check| check.run}
25
+ end
26
+
27
+ # Returns true if all checks passed.
28
+ def passed?
29
+ @update_on.all? {|check| check.passed?}
30
+ end
31
+
32
+ # Formated results.
33
+ def results
34
+ if @update_on.any? {|check| !check.passed?}
35
+ <<-EOS
36
+
37
+ Those gems can be updated to their latest version:
38
+
39
+ Name Local Remote
40
+ =========================================
41
+ #{@update_on.collect {|check| check.results}.join "\n"}
42
+
43
+ EOS
44
+ end
45
+ end
46
+ end
47
+
48
+ require "gem_watch/checks/update"
@@ -0,0 +1,7 @@
1
+ require 'test_helper'
2
+
3
+ class GemWatchTest < Test::Unit::TestCase
4
+ should "probably rename this file and start testing for real" do
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ require 'gem_watch'
8
+
9
+ class Test::Unit::TestCase
10
+ end
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gem_watch
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Fabien Jakimowicz
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-08-20 00:00:00 +02:00
13
+ default_executable: gemwatch
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: thoughtbot-shoulda
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: yaml
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ description: GemWatch watches over outdated gems in your system and send an email to inform administrators about available update, like apticron on debian
36
+ email: fabien@jakimowicz.com
37
+ executables:
38
+ - gemwatch
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - LICENSE
43
+ - README.rdoc
44
+ files:
45
+ - .document
46
+ - .gitignore
47
+ - LICENSE
48
+ - README.rdoc
49
+ - Rakefile
50
+ - VERSION
51
+ - bin/gemwatch
52
+ - lib/gem_watch.rb
53
+ - lib/gem_watch/check.rb
54
+ - lib/gem_watch/checks/update.rb
55
+ - lib/gem_watch/command.rb
56
+ - lib/gem_watch/command_options.rb
57
+ - test/gem_watch_test.rb
58
+ - test/test_helper.rb
59
+ has_rdoc: true
60
+ homepage: http://github.com/jakimowicz/gem_watch
61
+ post_install_message:
62
+ rdoc_options:
63
+ - --charset=UTF-8
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: "0"
71
+ version:
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: "0"
77
+ version:
78
+ requirements: []
79
+
80
+ rubyforge_project: gemwatch
81
+ rubygems_version: 1.3.1
82
+ signing_key:
83
+ specification_version: 2
84
+ summary: watch over outdated gems and send an email to notice admin.
85
+ test_files:
86
+ - test/gem_watch_test.rb
87
+ - test/test_helper.rb