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 +8 -3
- data/capnotify.gemspec +1 -1
- data/lib/capnotify.rb +30 -8
- data/lib/capnotify/component.rb +4 -0
- data/lib/capnotify/plugin.rb +43 -5
- data/lib/capnotify/plugin/details.rb +4 -2
- data/lib/capnotify/plugin/message.rb +33 -0
- data/lib/capnotify/plugin/overview.rb +8 -5
- data/lib/capnotify/templates/default_notification.html.erb +1 -0
- data/lib/capnotify/templates/default_notification.txt.erb +2 -1
- data/lib/capnotify/version.rb +1 -1
- data/spec/capnotify/plugin_spec.rb +45 -4
- metadata +14 -8
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
|
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
|
-
|
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
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(:
|
52
|
+
name = [ fetch(:stage, nil), fetch(:application, nil) ].compact.map{|c| c.capitalize}.join(" ")
|
41
53
|
if fetch(:branch, nil)
|
42
|
-
name = "#{ name }
|
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
|
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.
|
123
|
-
capnotify.load_plugin :capnotify_details, Capnotify::Plugin::Details
|
143
|
+
capnotify.load_default_plugins
|
124
144
|
end
|
125
145
|
|
126
|
-
|
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
|
data/lib/capnotify/component.rb
CHANGED
@@ -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)
|
data/lib/capnotify/plugin.rb
CHANGED
@@ -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
|
-
|
29
|
-
|
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(
|
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(
|
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
|
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(
|
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'] =
|
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
|
20
|
+
capnotify.delete_component PLUGIN_NAME
|
19
21
|
end
|
20
22
|
|
23
|
+
|
21
24
|
end
|
22
25
|
end
|
23
26
|
end
|
data/lib/capnotify/version.rb
CHANGED
@@ -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
|
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
|
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
|
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
|
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.
|
5
|
-
prerelease:
|
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-
|
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
|
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
|
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:
|
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:
|