capnotify 0.1.6pre → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -24,7 +24,7 @@ is made.
24
24
 
25
25
  Add this line to your application's Gemfile:
26
26
 
27
- gem 'capnotify'
27
+ gem "capnotify", "~> 0.1.6pre"
28
28
 
29
29
  And then execute:
30
30
 
@@ -32,7 +32,7 @@ And then execute:
32
32
 
33
33
  Or install it yourself as:
34
34
 
35
- $ gem install capnotify
35
+ $ gem install capnotify --pre
36
36
 
37
37
  Then, in your `Capfile`, add the following line:
38
38
 
@@ -354,9 +354,14 @@ also
354
354
  * getting component by name
355
355
  * lazy components
356
356
 
357
+ This should probably be in the wiki rather than the readme.
358
+
357
359
  ## Extensions
358
360
 
359
- Need to write this.
361
+ It's possible to write extensions for Capnotify. Typically, these will be used to add new
362
+ components to long messages.
363
+
364
+ Need to write this. This will probably wind up in the wiki instead of here.
360
365
 
361
366
  ## Contributing
362
367
 
data/capnotify.gemspec CHANGED
@@ -24,5 +24,5 @@ Gem::Specification.new do |spec|
24
24
  spec.add_development_dependency "pry"
25
25
  spec.add_development_dependency "awesome_print"
26
26
 
27
- spec.add_dependency "capistrano", "~> 2.14.2"
27
+ spec.add_dependency "capistrano", "~> 2.14"
28
28
  end
data/lib/capnotify.rb CHANGED
@@ -2,6 +2,7 @@ require 'capistrano'
2
2
  require "capnotify/version"
3
3
  require 'capnotify/component'
4
4
  require 'capnotify/plugin'
5
+ require 'capnotify/plugin/message'
5
6
  require 'capnotify/plugin/overview'
6
7
  require 'capnotify/plugin/details'
7
8
 
@@ -10,20 +11,27 @@ module Capnotify
10
11
  config.load do
11
12
  Capistrano.plugin :capnotify, ::Capnotify::Plugin
12
13
 
14
+ # conditionally set a capistrano var if it hasn't been set, yet.
15
+ # this functin was ganked from the built-in capistrano deploy recipe
16
+ # since we can't count on this function being defined, we redefine here.
13
17
  def _cset(name, *args, &block)
14
18
  unless exists?(name)
15
19
  set(name, *args, &block)
16
20
  end
17
21
  end
18
22
 
19
-
20
23
  # some configuration
24
+ # The paths to the built-in templates
25
+ # Set these in your deployment recipes if you want a custom template
26
+ # These paths are used when building the deployment notification emails
21
27
  _cset :capnotify_deployment_notification_html_template_path, capnotify.built_in_template_for('default_notification.html.erb')
22
28
  _cset :capnotify_deployment_notification_text_template_path, capnotify.built_in_template_for('default_notification.txt.erb')
23
29
 
24
30
  # get the name of the user deploying
25
31
  # if using git, this will read that from your git config
26
32
  # otherwise will use the currently logged-in user's name
33
+ # TODO: Support SCM other than git.
34
+ # TODO: Support a method other than `whoami` for getting the user's name
27
35
  _cset(:deployer_username) do
28
36
  if exists?(:scm) && fetch(:scm).to_sym == :git
29
37
  `git config user.name`.chomp
@@ -33,13 +41,17 @@ module Capnotify
33
41
  end
34
42
 
35
43
  # built-in values:
44
+
45
+ # This is the list of components to use for the notification
36
46
  set :capnotify_component_list, []
37
47
 
48
+ # The name of the application. Used in pretty much every built-in message
49
+ # by default, the output should be: "STAGE APPNAME @ BRANCH"
38
50
  # override this to change the default behavior for capnotify.appname
39
51
  _cset(:capnotify_appname) do
40
- name = [ fetch(:application, nil), fetch(:stage, nil) ].compact.join(" ")
52
+ name = [ fetch(:stage, nil), fetch(:application, nil) ].compact.map{|c| c.capitalize}.join(" ")
41
53
  if fetch(:branch, nil)
42
- name = "#{ name } / #{ branch }"
54
+ name = "#{ name } @ #{ branch }"
43
55
  end
44
56
  name
45
57
  end
@@ -78,11 +90,13 @@ module Capnotify
78
90
  end
79
91
 
80
92
  # full email message to notify of deployment (html)
93
+ # when called, will compile the template and return the complete data as a string
81
94
  _cset(:capnotify_deployment_notification_html) do
82
95
  capnotify.build_template( fetch(:capnotify_deployment_notification_html_template_path) )
83
96
  end
84
97
 
85
98
  # full email message to notify of deployment (plain text)
99
+ # when called, will compile the template and return the complete data as a string
86
100
  _cset(:capnotify_deployment_notification_text) do
87
101
  data = capnotify.build_template( fetch(:capnotify_deployment_notification_text_template_path) )
88
102
 
@@ -91,15 +105,20 @@ module Capnotify
91
105
  end
92
106
 
93
107
  # before update_code, fetch the current revision
94
- # this is needed to ensure that no matter when capnotify fetches the commit logs,
108
+ # this is needed to ensure that no matter when capnotify is run, it will have the correct previous (currently deployed) revision
95
109
  # it will have the correct starting point.
96
110
  before 'deploy:update_code' do
97
111
  set :capnotify_previous_revision, fetch(:current_revision, nil) # the revision that's currently deployed at this moment
98
112
  end
99
113
 
100
- # configure the callbacks
101
114
 
102
115
  on(:load) do
116
+ # register the callbacks
117
+ # These callbacks can be disabled by setting the following variables to a truthy value:
118
+ # * capnotify_disable_deploy_hooks
119
+ # * capnotify_disable_migrate_hooks
120
+ # * capnotify_disable_maintenance_hooks
121
+
103
122
  # deploy start/complete
104
123
  unless fetch(:capnotify_disable_deploy_hooks, false)
105
124
  before('deploy') { trigger :deploy_start }
@@ -118,12 +137,15 @@ module Capnotify
118
137
  after('deploy:web:enable') { trigger :maintenance_page_down }
119
138
  end
120
139
 
140
+ # load the default plugins
141
+ # disable loading them by setting capnotify_disable_default_components to a truthy value
121
142
  unless fetch(:capnotify_disable_default_components, false)
122
- capnotify.load_plugin :capnotify_overview, Capnotify::Plugin::Overview
123
- capnotify.load_plugin :capnotify_details, Capnotify::Plugin::Details
143
+ capnotify.load_default_plugins
124
144
  end
125
145
 
126
- capnotify.print_splash
146
+ # prints out a splash screen if capnotify_show_splash is set to true
147
+ # defaults to being silent.
148
+ capnotify.print_splash if fetch(:capnotify_show_splash, false)
127
149
  end
128
150
 
129
151
  end
@@ -45,6 +45,10 @@ module Capnotify
45
45
  @content
46
46
  end
47
47
 
48
+ # FIXME: this should probably leverage Procs for rendering of different types, maybe?
49
+ # that would give a lot of power to a developer who wants a custom format for a plugin (eg XML or JSON)
50
+ # Render the content in the given format using the right built-in template. Returns the content as a string.
51
+ # In the event that there is not a valid template, return an empty string.
48
52
  def render_content(format)
49
53
  begin
50
54
  ERB.new( File.open( template_path_for(format) ).read, nil, '%<>' ).result(self.get_binding)
@@ -4,9 +4,10 @@ require 'pry'
4
4
  module Capnotify
5
5
  module Plugin
6
6
 
7
+ # output a pretty splash screen of the Capnotify logo
8
+ # this can be enabled by setting capnotify_show_splash to a truthy value:
9
+ # set :capnotify_show_splash, true
7
10
  def print_splash
8
- return if fetch(:capnotify_hide_splash, false)
9
-
10
11
  puts <<-SPLASH
11
12
  __________________
12
13
  - --|\\ Deployment /| _____ __ _ ___
@@ -21,16 +22,52 @@ module Capnotify
21
22
  # convenience method for getting the friendly app name
22
23
  # If the stage is specified (the deployment is using multistage), include that.
23
24
  # given that the application is "MyApp" and the stage is "production", this will return "MyApp production"
25
+ # if capnotify_appname is not set, it'll return an empty string
24
26
  def appname
25
27
  fetch(:capnotify_appname, "")
26
28
  end
27
29
 
28
- def load_plugin(name, mod)
29
- Capistrano.plugin name, mod
30
+ # get the name of the deploying user
31
+ # currently this only supports git.
32
+ # if reading the git user.name, fall back on `whoami`
33
+ def deployed_by
34
+ username = nil
35
+
36
+ scm = fetch(:scm, nil)
37
+
38
+ if scm
39
+ if scm.to_sym == :git
40
+ username = `git config user.name`.chomp
41
+ username = nil if $? != 0 || username.strip == ''
42
+ end
43
+ end
44
+
45
+ username || `whoami`.chomp
46
+ end
47
+
48
+ # load the default built-in plugins
49
+ # this is called automatically when capistrano is done loading
50
+ # you can disable this (and not laod any plugins by default) by setting capnotify_disable_default_components
51
+ # set :capnotify_disable_default_components, true
52
+ def load_default_plugins
53
+ capnotify.load_plugin Capnotify::Plugin::Message
54
+ capnotify.load_plugin Capnotify::Plugin::Overview
55
+ capnotify.load_plugin Capnotify::Plugin::Details
56
+ end
57
+
58
+ # given a module name, load it as a plugin
59
+ # capnotify plugins must conform to the spec. See docs for info.
60
+ # mod should be the module itself, eg:
61
+ # capnotify.load_plugin Capnotify::Plugin::Message
62
+ def load_plugin(mod)
63
+ Capistrano.plugin mod::PLUGIN_NAME, mod
30
64
 
31
- get_plugin(name).init
65
+ get_plugin(mod::PLUGIN_NAME).init
32
66
  end
33
67
 
68
+ # given a plugin name as a symbol, unload the capnotify plugin
69
+ # this will also unload any kind of capistrano plugin
70
+ # if the plugin supports the unload method, it will be called.
34
71
  def unload_plugin(name)
35
72
  p = get_plugin(name)
36
73
 
@@ -38,6 +75,7 @@ module Capnotify
38
75
  Capistrano.remove_plugin(name)
39
76
  end
40
77
 
78
+ # given a plugin name, return the plugin.
41
79
  def get_plugin(name)
42
80
  raise "Unknown plugin: #{ name }" unless Capistrano::EXTENSIONS.keys.include?(name)
43
81
  self.send(name)
@@ -2,8 +2,10 @@ module Capnotify
2
2
  module Plugin
3
3
  module Details
4
4
 
5
+ PLUGIN_NAME = :capnotify_details
6
+
5
7
  def init
6
- capnotify.components << Capnotify::Component.new(:capnotify_details) do |c|
8
+ capnotify.components << Capnotify::Component.new(PLUGIN_NAME) do |c|
7
9
  c.header = 'Deployment Details'
8
10
 
9
11
  c.content = {}
@@ -18,7 +20,7 @@ module Capnotify
18
20
  end
19
21
 
20
22
  def unload
21
- capnotify.delete_component :capnotify_details
23
+ capnotify.delete_component PLUGIN_NAME
22
24
  end
23
25
 
24
26
  end
@@ -0,0 +1,33 @@
1
+ # Capnotify built-in plugin for Custom messages in email
2
+ # This adds a "message" section that will include 'notification_msg' if it's set
3
+ # For example:
4
+ # cap deploy -s notification_msg="Just getting a hotfix deployed"
5
+ module Capnotify
6
+ module Plugin
7
+ module Message
8
+
9
+ # the plugin's name (how it's referenced once it's loaded)
10
+ PLUGIN_NAME = :capnotify_message
11
+
12
+ # initialize the plugin
13
+ def init
14
+ # add a component tagged with this plugin's name
15
+ capnotify.components << Capnotify::Component.new(PLUGIN_NAME) do |c|
16
+ # the header
17
+ c.header = 'Message'
18
+
19
+ # the content
20
+ # if notification_msg isn't set, content will be set to nil
21
+ # nil content will prevent the section from being rendered.
22
+ c.content = fetch(:notification_msg, nil)
23
+ end
24
+ end
25
+
26
+ # delete the component when this plugin is unloaded
27
+ def unload
28
+ capnotify.delete_component PLUGIN_NAME
29
+ end
30
+
31
+ end
32
+ end
33
+ end
@@ -2,22 +2,25 @@ module Capnotify
2
2
  module Plugin
3
3
  module Overview
4
4
 
5
+ PLUGIN_NAME = :capnotify_overview
6
+
5
7
  def init
6
- capnotify.components << Capnotify::Component.new(:capnotify_overview) do |c|
8
+ capnotify.components << Capnotify::Component.new(PLUGIN_NAME) do |c|
7
9
  c.header = 'Deployment Overview'
8
10
 
9
11
  c.content = {}
10
- c.content['Deployed by'] = 'capnotify.deployed_by'
12
+ c.content['Deployed by'] = capnotify.deployed_by
11
13
  c.content['Deployed at'] = Time.now
12
- c.content['Application'] = fetch(:application, '')
13
- c.content['Repository'] = fetch(:repository, '')
14
+ c.content['Application'] = fetch(:application, 'n/a')
15
+ c.content['Repository'] = fetch(:repository, 'n/a')
14
16
  end
15
17
  end
16
18
 
17
19
  def unload
18
- capnotify.delete_component :capnotify_overview
20
+ capnotify.delete_component PLUGIN_NAME
19
21
  end
20
22
 
23
+
21
24
  end
22
25
  end
23
26
  end
@@ -64,6 +64,7 @@
64
64
  </h1>
65
65
 
66
66
  <% capnotify.components.each do |component| %>
67
+ <% next if component.content.nil? %>
67
68
  <div class="<%= component.css_class %>">
68
69
  <h2><%= component.header %></h2>
69
70
 
@@ -1,7 +1,8 @@
1
1
  <%= capnotify.appname %> deployment completed!
2
2
 
3
3
  <% capnotify.components.each do |component| %>
4
- --- <%= @header %> ---
4
+ <% next if component.content.nil? %>
5
+ --- <%= component.header %> ---
5
6
  <%= component.render_content(:txt) %>
6
7
  <% end %>
7
8
 
@@ -1,3 +1,3 @@
1
1
  module Capnotify
2
- VERSION = "0.1.6pre"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -19,6 +19,9 @@ describe Capnotify::Plugin do
19
19
  # a plugin for testing with
20
20
  # wires up init and unload to the ProxyObject
21
21
  module MyPlugin
22
+
23
+ PLUGIN_NAME = :my_plugin
24
+
22
25
  def init
23
26
  ProxyObject.instance.call_init
24
27
  end
@@ -65,7 +68,7 @@ describe Capnotify::Plugin do
65
68
 
66
69
  it "should load the plugin into capistrano" do
67
70
  config.load do
68
- capnotify.load_plugin :my_plugin, MyPlugin
71
+ capnotify.load_plugin MyPlugin
69
72
  end
70
73
 
71
74
  Capistrano::EXTENSIONS.keys.should include(:my_plugin)
@@ -75,7 +78,7 @@ describe Capnotify::Plugin do
75
78
  ProxyObject.instance.should_receive :call_init
76
79
 
77
80
  config.load do
78
- capnotify.load_plugin :my_plugin, MyPlugin
81
+ capnotify.load_plugin MyPlugin
79
82
  end
80
83
 
81
84
  end
@@ -86,7 +89,7 @@ describe Capnotify::Plugin do
86
89
 
87
90
  before do
88
91
  config.load do
89
- capnotify.load_plugin :my_plugin, MyPlugin
92
+ capnotify.load_plugin MyPlugin
90
93
  end
91
94
  end
92
95
 
@@ -115,7 +118,7 @@ describe Capnotify::Plugin do
115
118
  context "when plugin exists" do
116
119
  before do
117
120
  config.load do
118
- capnotify.load_plugin :my_plugin, MyPlugin
121
+ capnotify.load_plugin MyPlugin
119
122
  end
120
123
  end
121
124
 
@@ -149,6 +152,44 @@ describe Capnotify::Plugin do
149
152
  lambda { capnotify.build_template( capnotify.built_in_template_for('default_notification.txt.erb') ) }.should_not raise_error
150
153
  end
151
154
 
155
+ context "when building templates with components" do
156
+
157
+ let(:html_rendered_template) { capnotify.build_template( capnotify.built_in_template_for('default_notification.html.erb') ) }
158
+ let(:text_rendered_template) { capnotify.build_template( capnotify.built_in_template_for('default_notification.txt.erb') ) }
159
+
160
+ before do
161
+ capnotify.load_default_plugins
162
+ capnotify.components.count.should > 0
163
+ end
164
+
165
+ context "html templates" do
166
+ it "should not render components with no content" do
167
+ html_rendered_template.should_not match(/Message/) # the header
168
+ end
169
+
170
+ it "should render components with content" do
171
+ config.set :notification_msg, 'ASDFASDF'
172
+
173
+ html_rendered_template.should match(/Message/) # the header
174
+ html_rendered_template.should match(/ASDFASDF/) # the content
175
+ end
176
+ end
177
+
178
+ context "text templates" do
179
+ it "should not render components with no content" do
180
+ text_rendered_template.should_not match(/Message/) # the header
181
+ end
182
+
183
+ it "should render components with content" do
184
+ config.set :notification_msg, 'ASDFASDF'
185
+
186
+ text_rendered_template.should match(/Message/) # the header
187
+ text_rendered_template.should match(/ASDFASDF/) # the content
188
+ end
189
+ end
190
+
191
+ end
192
+
152
193
  end
153
194
 
154
195
  context "#components" do
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capnotify
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6pre
5
- prerelease: 5
4
+ version: 0.2.0
5
+ prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Spike Grobstein
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-03 00:00:00.000000000 Z
12
+ date: 2013-06-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -98,7 +98,7 @@ dependencies:
98
98
  requirements:
99
99
  - - ~>
100
100
  - !ruby/object:Gem::Version
101
- version: 2.14.2
101
+ version: '2.14'
102
102
  type: :runtime
103
103
  prerelease: false
104
104
  version_requirements: !ruby/object:Gem::Requirement
@@ -106,7 +106,7 @@ dependencies:
106
106
  requirements:
107
107
  - - ~>
108
108
  - !ruby/object:Gem::Version
109
- version: 2.14.2
109
+ version: '2.14'
110
110
  description: Extensible Capistrano notification system with helpers and sensible default
111
111
  values for common notification tasks.
112
112
  email:
@@ -127,6 +127,7 @@ files:
127
127
  - lib/capnotify/component.rb
128
128
  - lib/capnotify/plugin.rb
129
129
  - lib/capnotify/plugin/details.rb
130
+ - lib/capnotify/plugin/message.rb
130
131
  - lib/capnotify/plugin/overview.rb
131
132
  - lib/capnotify/templates/_component.html.erb
132
133
  - lib/capnotify/templates/_component.txt.erb
@@ -150,12 +151,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
150
151
  - - ! '>='
151
152
  - !ruby/object:Gem::Version
152
153
  version: '0'
154
+ segments:
155
+ - 0
156
+ hash: -27722869543230501
153
157
  required_rubygems_version: !ruby/object:Gem::Requirement
154
158
  none: false
155
159
  requirements:
156
- - - ! '>'
160
+ - - ! '>='
157
161
  - !ruby/object:Gem::Version
158
- version: 1.3.1
162
+ version: '0'
163
+ segments:
164
+ - 0
165
+ hash: -27722869543230501
159
166
  requirements: []
160
167
  rubyforge_project:
161
168
  rubygems_version: 1.8.24
@@ -167,4 +174,3 @@ test_files:
167
174
  - spec/capnotify/plugin_spec.rb
168
175
  - spec/capnotify_spec.rb
169
176
  - spec/spec_helper.rb
170
- has_rdoc: