capnotify 0.1.6pre → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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:
|