ops_routes 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2010 PRIMEDIA Inc.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
data/README.rdoc ADDED
@@ -0,0 +1,62 @@
1
+ = Operations Routes
2
+
3
+ This library provides a Rails plugin and a piece of Rack middleware for monitoring application status. When using with a Rails application, the plugin is preferred, but the middleware is available for use in non-Rails Rack applications.
4
+
5
+ *Note:* Previous versions of this library were available as the gem <tt>operations_middleware</tt> and included only the middleware portion.
6
+
7
+ == Installation
8
+
9
+ To include it in a Rails application, install the plugin:
10
+
11
+ script/plugin install https://duien@github.com/primedia/ops_routes.git
12
+
13
+ Then add the following minimum configuration to <tt>config/initializers/ops_routes.rb</tt>:
14
+
15
+ OpsRoutes.config do |ops|
16
+ ops.file_root = RAILS_ROOT
17
+ end
18
+
19
+ To include it in a Sinatra application, install the gem <tt>ops_routes</tt> then add the following to your app:
20
+
21
+ require 'ops_routes/middleware'
22
+ use OpsRoutes::Middleware do |ops|
23
+ ops.file_root = File.dirname(__FILE__)
24
+ end
25
+
26
+ == Version Page
27
+
28
+ This will provide a page at <tt>/ops/version</tt> which shows, in development mode, the current git branch and last commit SHA. In all other modes, it shows the same information, but taken from the contents of VERSION and REVISION files in the <tt>file_root</tt> directory. If you are deploying with Capistrano, the REVISION file will be created for you. If you want the VERSION file, you'll need to add that to your project or your Capistrano scripts.
29
+
30
+ == Heartbeat Page
31
+
32
+ It also provides a simple page at <tt>/ops/heartbeat</tt> which returns a 200 'OK' as long as the application is running.
33
+
34
+ The application name is taken from the <tt>file_root</tt> option. If that folder is a Capistrano timestamped release, it goes up 2 additional levels for the name, stripping <tt>.com</tt> from the end of the directory if necessary. If this logic does not get the correct application name, it can be set manually in the configuration block:
35
+
36
+ ops.app_name = 'Custom Application Name'
37
+
38
+ === Adding Custom Heartbeats
39
+
40
+ Additionally, you can specify custom heartbeat monitoring pages as follows:
41
+
42
+ ops.add_heartbeat :mysql do
43
+ conn = ActiveRecord::Base.connection
44
+ migrations = conn.select_all("SELECT COUNT(1) FROM schema_migrations;")
45
+ conn.disconnect!
46
+ end
47
+
48
+ The mysql example shown above would be accessed at <tt>ops/heartbeat/mysql</tt>. The heartbeat page will return a 200 'OK' as long as the provided block does not raise an error. If an error is raised or the heartbeat does not exist, a 500 will be returned instead.
49
+
50
+ == Note on Patches/Pull Requests
51
+
52
+ * Fork the project.
53
+ * Make your feature addition or bug fix.
54
+ * Add tests for it. This is important so I don't break it in a
55
+ future version unintentionally.
56
+ * Commit, do not mess with rakefile, version, or history.
57
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
58
+ * Send me a pull request. Bonus points for topic branches.
59
+
60
+ == Copyright
61
+
62
+ Copyright (c) 2010 PRIMEDIA Inc. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,49 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "ops_routes"
8
+ gem.summary = %Q{Plugin or middleware that provides version and heartbeat pages for app monitoring}
9
+ gem.description = %Q{Installs as Rails plugin or Rack middleware for non-Rails apps}
10
+ gem.email = ""
11
+ gem.homepage = "http://github.com/primedia/ops_routes"
12
+ gem.authors = ["Primedia Team"]
13
+ gem.add_dependency "rack", "~> 1.0"
14
+ gem.add_dependency "haml", "~> 3.0.0"
15
+ gem.add_development_dependency "rspec", ">= 1.2.9"
16
+ gem.add_development_dependency "rack-test"
17
+ gem.add_development_dependency 'rspec_tag_matchers'
18
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
19
+ end
20
+ Jeweler::GemcutterTasks.new
21
+ rescue LoadError
22
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
23
+ end
24
+
25
+ require 'spec/rake/spectask'
26
+ Spec::Rake::SpecTask.new(:spec) do |spec|
27
+ spec.libs << 'lib' << 'spec'
28
+ spec.spec_files = FileList['spec/**/*_spec.rb']
29
+ end
30
+
31
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
32
+ spec.libs << 'lib' << 'spec'
33
+ spec.pattern = 'spec/**/*_spec.rb'
34
+ spec.rcov = true
35
+ end
36
+
37
+ task :spec => :check_dependencies
38
+
39
+ task :default => :spec
40
+
41
+ require 'rake/rdoctask'
42
+ Rake::RDocTask.new do |rdoc|
43
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
44
+
45
+ rdoc.rdoc_dir = 'rdoc'
46
+ rdoc.title = "ops_routes #{version}"
47
+ rdoc.rdoc_files.include('README*')
48
+ rdoc.rdoc_files.include('lib/**/*.rb')
49
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.4.0
@@ -0,0 +1,12 @@
1
+ class OpsController < ApplicationController
2
+
3
+ def version
4
+ render :text => OpsRoutes.check_version(request.headers)
5
+ end
6
+
7
+ def heartbeat
8
+ response.content_type = "text/plain"
9
+ render OpsRoutes.check_heartbeat(params[:name])
10
+ end
11
+
12
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,5 @@
1
+ ActionController::Routing::Routes.draw do |map|
2
+ map.connect '/ops/version', :controller => 'ops', :action => 'version'
3
+ map.connect '/ops/heartbeat', :controller => 'ops', :action => 'heartbeat'
4
+ map.connect '/ops/heartbeat/:name', :controller => 'ops', :action => 'heartbeat'
5
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ # Include hook code here
data/install.rb ADDED
@@ -0,0 +1 @@
1
+ # Install hook code here
@@ -0,0 +1,27 @@
1
+ require File.join(File.dirname(File.dirname(__FILE__)), 'ops_routes')
2
+
3
+ module OpsRoutes
4
+ class Middleware
5
+ def initialize(app)
6
+ @app = app
7
+ yield OpsRoutes if block_given?
8
+ end
9
+
10
+ def call(env)
11
+ return @app.call(env) unless env['PATH_INFO'] =~ %r{^/ops/(heartbeat|version)(?:/(\w+))?/?$}
12
+ route, heartbeat_name = $1, $2
13
+ case route
14
+ when 'heartbeat'
15
+ heartbeat_result = OpsRoutes.check_heartbeat(heartbeat_name)
16
+ headers = { 'Content-Type' => 'text/plain',
17
+ 'Content-Length' => heartbeat_result[:text].length.to_s }
18
+ [ heartbeat_result[:status], headers, [heartbeat_result[:text]] ]
19
+ when 'version'
20
+ version_result = OpsRoutes.check_version(env)
21
+ headers = { 'Content-Type' => 'text/html',
22
+ 'Content-Length' => version_result.length.to_s }
23
+ [ 200, headers, [version_result] ]
24
+ end
25
+ end
26
+ end
27
+ end
data/lib/ops_routes.rb ADDED
@@ -0,0 +1,115 @@
1
+ require 'haml'
2
+
3
+ module OpsRoutes
4
+
5
+ class << self
6
+
7
+ attr_writer :app_name
8
+ attr_accessor :file_root
9
+
10
+ def config
11
+ yield OpsRoutes if block_given?
12
+ end
13
+ # Heartbeats
14
+
15
+ def heartbeats
16
+ @heartbeats ||= {}
17
+ end
18
+
19
+ def add_heartbeat(name, &block)
20
+ heartbeats[name] = block
21
+ end
22
+
23
+ def check_heartbeat(name = nil)
24
+ if name
25
+ begin
26
+ heartbeats[name.to_sym].call
27
+ return { :status => 200, :text => "#{name} is OK" }
28
+ rescue
29
+ return { :status => 500, :text => "#{name} does not have a heartbeat" }
30
+ end
31
+ else
32
+ return { :status => 200, :text => 'OK' }
33
+ end
34
+ end
35
+
36
+ # Version page
37
+
38
+ def check_version(headers={})
39
+ @headers = headers
40
+ version_template = File.join(File.dirname(__FILE__), 'views', 'version.html.haml')
41
+ Haml::Engine.new(File.read(version_template)).render(self)
42
+ end
43
+
44
+ def version_or_branch
45
+ @version ||= if File.exists?(version_file)
46
+ File.read(version_file).chomp.gsub('^{}', '')
47
+ elsif environment == 'development' && `git branch` =~ /^\* (.*)$/
48
+ $1
49
+ else
50
+ 'Unknown (VERSION file is missing)'
51
+ end
52
+ end
53
+
54
+ def version_file
55
+ @version_file ||= File.join(file_root, 'VERSION')
56
+ end
57
+
58
+ def environment
59
+ ENV['RAILS_ENV']
60
+ end
61
+
62
+ def deploy_date
63
+ @deploy_date ||= if File.exists?(version_file)
64
+ File.stat(version_file).mtime
65
+ elsif environment == 'development'
66
+ 'Live'
67
+ else
68
+ 'Unknown (VERSION file is missing)'
69
+ end
70
+ end
71
+
72
+ def last_commit
73
+ @last_commit ||= if File.exists?(revision_file)
74
+ File.read(revision_file).chomp
75
+ elsif environment == 'development' && `git show` =~ /^commit (.*)$/
76
+ $1
77
+ else
78
+ 'Unknown (REVISION file is missing)'
79
+ end
80
+ end
81
+
82
+ def revision_file
83
+ @revision_file ||= File.join(file_root, 'REVISION')
84
+ end
85
+
86
+ def hostname
87
+ @hostname ||= `/bin/hostname` || 'Unknown'
88
+ end
89
+
90
+ def app_name
91
+ @app_name ||= begin
92
+ dirs = Dir.pwd.split('/')
93
+ if dirs.last =~ /^\d+$/
94
+ dirs[-3]
95
+ else
96
+ dirs.last
97
+ end.sub(/\.com$/, '')
98
+ end
99
+ end
100
+
101
+ def headers
102
+ @headers.select{|k,v| k.match(/^[-A-Z_].*$/) }
103
+ end
104
+
105
+ def version_link
106
+ "https://github.com/primedia/#{app_name}/tree/#{version_or_branch}" unless version_or_branch =~ /^Unknown/
107
+ end
108
+
109
+ def last_commit_link
110
+ "https://github.com/primedia/#{app_name}/commit/#{last_commit}" unless version_or_branch =~ /^Unknown/
111
+ end
112
+
113
+ end
114
+
115
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :ops_routes do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,45 @@
1
+ !!!
2
+ %head
3
+ %title= app_name
4
+ :css
5
+ .container {font-size: 20px; width: 1000px; padding-bottom: 100px;}
6
+ .label {float: left; width: 400px; font-weight: bold}
7
+ .spacer {clear: both; padding: 10px;}
8
+ .value {float: left; width: 500px; text-align: right;}
9
+ #headers .value {clear: both; width: 1000px; text-align: left;}
10
+ #headers .value tr.even {background: #dddddd;}
11
+ .clear {clear: both;}
12
+ %body
13
+ .container
14
+ .spacer
15
+ #version
16
+ .label= "#{app_name} Version"
17
+ .value
18
+ %a{:href => version_link}= version_or_branch
19
+ .spacer
20
+ #date
21
+ .label Date Deployed
22
+ .value= deploy_date
23
+ .spacer
24
+ #commit
25
+ .label Last Commit
26
+ .value
27
+ %a{:href => last_commit_link}= last_commit
28
+ .spacer
29
+ #host
30
+ .label Host
31
+ .value= hostname
32
+ .spacer
33
+ #environment
34
+ .label Environment
35
+ .value= environment
36
+ .spacer
37
+ #headers
38
+ .label Headers
39
+ .value
40
+ %table
41
+ - headers.sort_by{ |h| h.first }.each_with_index do |(header, value), i|
42
+ %tr{ :class => i%2==0 ? 'even' : nil }
43
+ %td= header
44
+ %td= value
45
+ .clear
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ # Weird hacky controller specs since spec/rails explodes outside a Rails app
4
+ describe OpsController do
5
+ let(:controller) do
6
+ c = OpsController.new
7
+ c.stub(:request).and_return(mock('request', :headers => {}))
8
+ c.stub(:response).and_return(mock('response', :content_type= => true))
9
+ c
10
+ end
11
+
12
+ it "should respond to version" do
13
+ version_page = mock('version page')
14
+ OpsRoutes.should_receive(:check_version).and_return(version_page)
15
+ controller.should_receive(:render).with(:text => version_page)
16
+ controller.version
17
+ end
18
+
19
+ it "should respond to heartbeat for unnamed heartbeat" do
20
+ controller.stub(:params).and_return({})
21
+ heartbeat_page = mock('heartbeat page')
22
+ OpsRoutes.should_receive(:check_heartbeat).with(nil).and_return(heartbeat_page)
23
+ controller.should_receive(:render).with(heartbeat_page)
24
+ controller.heartbeat
25
+ end
26
+
27
+ it "should respond to heartbeat for named heartbeat" do
28
+ controller.stub(:params).and_return({:name => 'foo'})
29
+ heartbeat_page = mock('heartbeat page')
30
+ OpsRoutes.should_receive(:check_heartbeat).with('foo').and_return(heartbeat_page)
31
+ controller.should_receive(:render).with(heartbeat_page)
32
+ controller.heartbeat
33
+ end
34
+
35
+ end
@@ -0,0 +1,74 @@
1
+ require 'spec_helper'
2
+
3
+ describe OpsRoutes::Middleware do
4
+
5
+ before do
6
+ @parent_app = mock("Rails App")
7
+ @parent_app.stub(:call).and_return([200, {}, ['Parent App']])
8
+ @parent_app.stub(:env).and_return({})
9
+ end
10
+
11
+ def app
12
+ @app ||= OpsRoutes::Middleware.new(@parent_app) do |ops|
13
+ ops.file_root = File.join(File.dirname(__FILE__), '..')
14
+ end
15
+ end
16
+
17
+ context "passing routes" do
18
+
19
+ it "should pass to parent app for /" do
20
+ @parent_app.should_receive(:call)
21
+ get '/'
22
+ end
23
+
24
+ it "should pass to parent app for /Georgia/Atlanta" do
25
+ @parent_app.should_receive(:call)
26
+ get '/Georgia/Atlanta'
27
+ end
28
+
29
+ end
30
+
31
+ context "captured routes" do
32
+
33
+ context "version" do
34
+
35
+ it "should not pass to parent app for '/ops/version'" do
36
+ @parent_app.should_not_receive(:call)
37
+ get '/ops/version'
38
+ end
39
+
40
+ it "should call check_version" do
41
+ OpsRoutes.should_receive(:check_version).and_return("The version page")
42
+ get '/ops/version'
43
+ end
44
+
45
+ end
46
+
47
+ context "heartbeat" do
48
+
49
+ it "should not pass to parent app for '/ops/heartbeat'" do
50
+ @parent_app.should_not_receive(:call)
51
+ get '/ops/version'
52
+ end
53
+
54
+ it 'should call check_heartbeat' do
55
+ OpsRoutes.should_receive(:check_heartbeat).with(nil).and_return(
56
+ :status => 200,
57
+ :text => 'OK')
58
+ get '/ops/heartbeat'
59
+ end
60
+
61
+ context "named heartbeat" do
62
+ it 'should call check_heartbeat with heartbeat name' do
63
+ OpsRoutes.should_receive(:check_heartbeat).with('foo').and_return(
64
+ :status => 200,
65
+ :text => 'OK')
66
+ get '/ops/heartbeat/foo'
67
+ end
68
+ end
69
+
70
+ end
71
+
72
+ end
73
+
74
+ end
@@ -0,0 +1,220 @@
1
+ require 'spec_helper'
2
+
3
+ describe OpsRoutes do
4
+
5
+ before do
6
+ OpsRoutes.instance_variables.each do |var|
7
+ OpsRoutes.method(:remove_instance_variable).call(var)
8
+ end
9
+ OpsRoutes.stub(:file_root).and_return(File.dirname(__FILE__))
10
+ end
11
+
12
+ describe ".check_version" do
13
+ it "should have version link" do
14
+ OpsRoutes.stub(:app_name).and_return('App')
15
+ OpsRoutes.stub(:version_or_branch).and_return('branch')
16
+ version_page = OpsRoutes.check_version({})
17
+ version_page.should have_tag('#version .label', 'App Version')
18
+ version_page.should have_tag('#version .value a', 'branch')
19
+ end
20
+
21
+ it "should have date deployed" do
22
+ OpsRoutes.stub(:deploy_date).and_return('now')
23
+ version_page = OpsRoutes.check_version({})
24
+ version_page.should have_tag('#date .label', 'Date Deployed')
25
+ version_page.should have_tag('#date .value', 'now')
26
+ end
27
+
28
+ it "should have last commit" do
29
+ OpsRoutes.stub(:last_commit).and_return('mock_sha')
30
+ version_page = OpsRoutes.check_version({})
31
+ version_page.should have_tag('#commit .label', 'Last Commit')
32
+ version_page.should have_tag('#commit .value a', 'mock_sha')
33
+ end
34
+
35
+ it "should have host" do
36
+ OpsRoutes.stub(:hostname).and_return('host')
37
+ version_page = OpsRoutes.check_version({})
38
+ version_page.should have_tag('#host .label', 'Host')
39
+ version_page.should have_tag('#host .value', 'host')
40
+ end
41
+
42
+ it "should have headers" do
43
+ OpsRoutes.stub(:headers).and_return({'header' => 'value'})
44
+ version_page = OpsRoutes.check_version({})
45
+ version_page.should have_tag('#headers .label', 'Headers')
46
+ version_page.should have_tag('#headers .value td', 'header')
47
+ version_page.should have_tag('#headers .value td', 'value')
48
+ end
49
+
50
+ it "should have environment" do
51
+ OpsRoutes.stub(:environment).and_return('env')
52
+ version_page = OpsRoutes.check_version({})
53
+ version_page.should have_tag('#environment .label', 'Environment')
54
+ version_page.should have_tag('#environment .value', 'env')
55
+ end
56
+
57
+ it "should render a valid html page" do
58
+ version_page = OpsRoutes.check_version({})
59
+ version_page.should have_tag('html')
60
+ version_page.should have_tag('head')
61
+ version_page.should have_tag('body')
62
+ end
63
+
64
+ end
65
+
66
+ describe ".check_heartbeat" do
67
+
68
+ it "should return 200 'OK' with no params" do
69
+ heartbeat = OpsRoutes.check_heartbeat
70
+ heartbeat[:status].should == 200
71
+ heartbeat[:text].should == 'OK'
72
+ end
73
+
74
+ it "should return 200 '<name> is OK' with named heartbeat" do
75
+ OpsRoutes.add_heartbeat(:foo) do
76
+ "All is well"
77
+ end
78
+ heartbeat = OpsRoutes.check_heartbeat('foo')
79
+ heartbeat[:status].should == 200
80
+ heartbeat[:text].should == 'foo is OK'
81
+ end
82
+
83
+ it "should return 500 '<name> does not have a heartbeat' with invalid named heartbeat" do
84
+ heartbeat = OpsRoutes.check_heartbeat('foo')
85
+ heartbeat[:status].should == 500
86
+ heartbeat[:text].should == 'foo does not have a heartbeat'
87
+ end
88
+
89
+ it "should return 500 '<name> does not have a heartbeat' if heartbeat fails" do
90
+ OpsRoutes.add_heartbeat(:foo) do
91
+ raise
92
+ end
93
+ heartbeat = OpsRoutes.check_heartbeat('foo')
94
+ heartbeat[:status].should == 500
95
+ heartbeat[:text].should == 'foo does not have a heartbeat'
96
+ end
97
+
98
+ end
99
+
100
+ describe '.app_name' do
101
+
102
+ it "should return config option if given" do
103
+ OpsRoutes.app_name = 'Config App'
104
+ OpsRoutes.app_name.should == 'Config App'
105
+ end
106
+
107
+ it "should return parent directory if not a timestamp" do
108
+ Dir.stub(:pwd).and_return('/foo/bar')
109
+ OpsRoutes.app_name.should == 'bar'
110
+ end
111
+
112
+ it "should return 2 levels up from parent if parent is timestamp (cap deploy structure)" do
113
+ Dir.stub(:pwd).and_return('/app/releases/12345')
114
+ OpsRoutes.app_name.should == 'app'
115
+ end
116
+
117
+ it "should strip '.com' off of parent name" do
118
+ Dir.stub(:pwd).and_return('/app.com/releases/12345')
119
+ OpsRoutes.app_name.should == 'app'
120
+ end
121
+
122
+ end
123
+
124
+ describe '.version_or_branch' do
125
+ it "should use contents of VERSION file if available" do
126
+ File.stub(:exists?).with(File.join(OpsRoutes.file_root, 'VERSION')).and_return(true)
127
+ File.stub(:read).with(File.join(OpsRoutes.file_root, 'VERSION')).and_return('version')
128
+
129
+ OpsRoutes.version_or_branch.should == 'version'
130
+ end
131
+
132
+ it "should use current git branch if in git repo and development mode" do
133
+ File.stub(:exists?).with(File.join(OpsRoutes.file_root, 'VERSION')).and_return(false)
134
+ # stub on app instead of Kernel since apparently you can't stub on a Module
135
+ OpsRoutes.stub(:`).with('git branch').and_return("* foo\n bar")
136
+ OpsRoutes.stub(:environment).and_return('development')
137
+
138
+ OpsRoutes.version_or_branch.should == 'foo'
139
+ end
140
+
141
+ it "should be unknown if not in git repo" do
142
+ File.stub(:exists?).with(File.join(OpsRoutes.file_root, 'VERSION')).and_return(false)
143
+ # stub on OpsRoutes instead of Kernel since apparently you can't stub on a Module
144
+ OpsRoutes.stub(:`).with('git branch').and_return("fatal: Not a git repository (or any of the parent directories): .git")
145
+ OpsRoutes.stub(:environment).and_return('development')
146
+
147
+ OpsRoutes.version_or_branch.should match('^Unknown')
148
+ end
149
+
150
+ it "should be unknown if not in development mode" do
151
+ File.stub(:exists?).with(File.join(OpsRoutes.file_root, 'VERSION')).and_return(false)
152
+ # stub on OpsRoutes instead of Kernel since apparently you can't stub on a Module
153
+ OpsRoutes.stub(:`).with('git branch').and_return("* foo\n bar")
154
+ OpsRoutes.stub(:environment).and_return('production')
155
+
156
+ OpsRoutes.version_or_branch.should match('^Unknown')
157
+ end
158
+
159
+ end
160
+
161
+ describe '.deploy_date' do
162
+ it "should use mtime of VERSION file if available" do
163
+ time = mock('time')
164
+ time.stub(:mtime).and_return('timestamp')
165
+ File.stub(:exists?).with(File.join(OpsRoutes.file_root, 'VERSION')).and_return(true)
166
+ File.stub(:stat).with(File.join(OpsRoutes.file_root, 'VERSION')).and_return(time)
167
+
168
+ OpsRoutes.deploy_date.should == 'timestamp'
169
+ end
170
+
171
+ it "should use 'Live' if in development" do
172
+ File.stub(:exists?).with(File.join(OpsRoutes.file_root, 'VERSION')).and_return(false)
173
+ OpsRoutes.stub(:environment).and_return('development')
174
+
175
+ OpsRoutes.deploy_date.should == 'Live'
176
+ end
177
+
178
+ it "should use unknown if not development" do
179
+ File.stub(:exists?).with(File.join(OpsRoutes.file_root, 'VERSION')).and_return(false)
180
+ OpsRoutes.stub(:environment).and_return('production')
181
+
182
+ OpsRoutes.deploy_date.should match('^Unknown')
183
+ end
184
+ end
185
+
186
+ describe '.last_commit' do
187
+ it "should use contents of REVISION file if available" do
188
+ File.stub(:exists?).with(File.join(OpsRoutes.file_root, 'REVISION')).and_return(true)
189
+ File.stub(:read).with(File.join(OpsRoutes.file_root, 'REVISION')).and_return('some_sha')
190
+
191
+ OpsRoutes.last_commit.should == 'some_sha'
192
+ end
193
+
194
+ it "should use current git HEAD if in git repo and development mode" do
195
+ File.stub(:exists?).with(File.join(OpsRoutes.file_root, 'REVISION')).and_return(false)
196
+ OpsRoutes.stub(:`).with('git show').and_return("commit some_sha")
197
+ OpsRoutes.stub(:environment).and_return('development')
198
+
199
+ OpsRoutes.last_commit.should == 'some_sha'
200
+ end
201
+
202
+ it "should be unknown if not in git repo" do
203
+ File.stub(:exists?).with(File.join(OpsRoutes.file_root, 'REVISION')).and_return(false)
204
+ OpsRoutes.stub(:`).with('git show').and_return("fatal: Not a git repository (or any of the parent directories): .git")
205
+ OpsRoutes.stub(:environment).and_return('development')
206
+
207
+ OpsRoutes.last_commit.should match('^Unknown')
208
+ end
209
+
210
+ it "should be unknown if not in development mode" do
211
+ File.stub(:exists?).with(File.join(OpsRoutes.file_root, 'REVISION')).and_return(false)
212
+ OpsRoutes.stub(:`).with('git show').and_return("commit some_sha")
213
+ OpsRoutes.stub(:environment).and_return('production')
214
+
215
+ OpsRoutes.last_commit.should match('^Unknown')
216
+ end
217
+
218
+ end
219
+
220
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ -fn
@@ -0,0 +1,24 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'app', 'controllers'))
4
+ require 'ops_routes'
5
+ require 'ops_routes/middleware'
6
+
7
+ # Define app controller since we're not in a rails app
8
+ class ApplicationController
9
+ end
10
+ require 'ops_controller'
11
+
12
+ require 'rubygems'
13
+ gem 'rack', '~>1.0'
14
+ require 'rack'
15
+ require 'spec'
16
+ # require 'spec/rails'
17
+ require 'spec/autorun'
18
+ require 'rack/test'
19
+ require 'rspec_tag_matchers'
20
+
21
+ Spec::Runner.configure do |config|
22
+ include Rack::Test::Methods
23
+ config.include(RspecTagMatchers)
24
+ end
data/uninstall.rb ADDED
@@ -0,0 +1 @@
1
+ # Uninstall hook code here
metadata ADDED
@@ -0,0 +1,147 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ops_routes
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 4
8
+ - 0
9
+ version: 0.4.0
10
+ platform: ruby
11
+ authors:
12
+ - Primedia Team
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-08-09 00:00:00 -04:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rack
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 1
29
+ - 0
30
+ version: "1.0"
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: haml
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ segments:
41
+ - 3
42
+ - 0
43
+ - 0
44
+ version: 3.0.0
45
+ type: :runtime
46
+ version_requirements: *id002
47
+ - !ruby/object:Gem::Dependency
48
+ name: rspec
49
+ prerelease: false
50
+ requirement: &id003 !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ segments:
55
+ - 1
56
+ - 2
57
+ - 9
58
+ version: 1.2.9
59
+ type: :development
60
+ version_requirements: *id003
61
+ - !ruby/object:Gem::Dependency
62
+ name: rack-test
63
+ prerelease: false
64
+ requirement: &id004 !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ segments:
69
+ - 0
70
+ version: "0"
71
+ type: :development
72
+ version_requirements: *id004
73
+ - !ruby/object:Gem::Dependency
74
+ name: rspec_tag_matchers
75
+ prerelease: false
76
+ requirement: &id005 !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ segments:
81
+ - 0
82
+ version: "0"
83
+ type: :development
84
+ version_requirements: *id005
85
+ description: Installs as Rails plugin or Rack middleware for non-Rails apps
86
+ email: ""
87
+ executables: []
88
+
89
+ extensions: []
90
+
91
+ extra_rdoc_files:
92
+ - LICENSE
93
+ - README.rdoc
94
+ files:
95
+ - LICENSE
96
+ - README.rdoc
97
+ - Rakefile
98
+ - VERSION
99
+ - app/controllers/ops_controller.rb
100
+ - config/routes.rb
101
+ - init.rb
102
+ - install.rb
103
+ - lib/ops_routes.rb
104
+ - lib/ops_routes/middleware.rb
105
+ - lib/tasks/ops_routes.rake
106
+ - lib/views/version.html.haml
107
+ - spec/app/controllers/ops_controller_spec.rb
108
+ - spec/ops_routes/middleware_spec.rb
109
+ - spec/ops_routes_spec.rb
110
+ - spec/spec.opts
111
+ - spec/spec_helper.rb
112
+ - uninstall.rb
113
+ has_rdoc: true
114
+ homepage: http://github.com/primedia/ops_routes
115
+ licenses: []
116
+
117
+ post_install_message:
118
+ rdoc_options:
119
+ - --charset=UTF-8
120
+ require_paths:
121
+ - lib
122
+ required_ruby_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ segments:
127
+ - 0
128
+ version: "0"
129
+ required_rubygems_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ segments:
134
+ - 0
135
+ version: "0"
136
+ requirements: []
137
+
138
+ rubyforge_project:
139
+ rubygems_version: 1.3.6
140
+ signing_key:
141
+ specification_version: 3
142
+ summary: Plugin or middleware that provides version and heartbeat pages for app monitoring
143
+ test_files:
144
+ - spec/app/controllers/ops_controller_spec.rb
145
+ - spec/ops_routes/middleware_spec.rb
146
+ - spec/ops_routes_spec.rb
147
+ - spec/spec_helper.rb