heroku_san 2.0.0 → 2.1.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/CHANGELOG.md +33 -0
- data/README.rdoc +41 -31
- data/examples/push_revision.rake +8 -0
- data/features/config.feature +2 -0
- data/lib/git.rb +13 -5
- data/lib/heroku_san.rb +1 -0
- data/lib/heroku_san/stage.rb +31 -7
- data/lib/heroku_san/version.rb +1 -1
- data/lib/tasks.rb +119 -94
- data/spec/git_spec.rb +19 -0
- data/spec/heroku_san/stage_spec.rb +88 -1
- metadata +18 -16
data/CHANGELOG.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# Change log (curated)
|
2
|
+
|
3
|
+
## v2.1.0
|
4
|
+
|
5
|
+
* Documentation update
|
6
|
+
* Push `REVISION` to Heroku example
|
7
|
+
* Bug fixes
|
8
|
+
|
9
|
+
### New tasks
|
10
|
+
|
11
|
+
* rake logs:tail
|
12
|
+
* rake shell
|
13
|
+
* All HerokuSan tasks inside heroku: namespace, with aliases in the global namespace
|
14
|
+
|
15
|
+
### New methods
|
16
|
+
|
17
|
+
* `Stage#deploy`
|
18
|
+
* `Stage#maintenance` can now take a block, and ensures that maintenance mode is off afterwards.
|
19
|
+
* `Stage#push_config`
|
20
|
+
|
21
|
+
## v2.0.0
|
22
|
+
|
23
|
+
* Major rewrite into classes `Project` & `Stage`, with helper `Git` module
|
24
|
+
* Tests for _everything_
|
25
|
+
* Examples directory (e.g. `auto-tagger`)
|
26
|
+
* Removed dependencies on Rails
|
27
|
+
* `tasks.rb` is greatly simplified, mostly API calls into the `Stage` class
|
28
|
+
* Support for tagging releases and deploying apps using a tag glob
|
29
|
+
* Support for Heroku stacks (aspen, bamboo & cedar)
|
30
|
+
|
31
|
+
## v1.3.0
|
32
|
+
|
33
|
+
N/A
|
data/README.rdoc
CHANGED
@@ -68,37 +68,47 @@ Need to add remotes for each app?
|
|
68
68
|
|
69
69
|
A full list of tasks provided:
|
70
70
|
|
71
|
-
rake
|
72
|
-
rake
|
73
|
-
rake
|
74
|
-
rake
|
75
|
-
rake
|
76
|
-
rake
|
77
|
-
rake
|
78
|
-
rake
|
79
|
-
rake
|
80
|
-
rake heroku:
|
81
|
-
rake heroku:
|
82
|
-
rake heroku:
|
83
|
-
rake heroku:
|
84
|
-
rake heroku:
|
85
|
-
rake heroku:
|
86
|
-
rake heroku:
|
87
|
-
rake heroku:
|
88
|
-
rake heroku:maintenance
|
89
|
-
rake heroku:maintenance_off
|
90
|
-
rake heroku:
|
91
|
-
rake heroku:push
|
92
|
-
rake heroku:
|
93
|
-
rake heroku:rake[task]
|
94
|
-
rake heroku:remotes
|
95
|
-
rake heroku:
|
96
|
-
rake heroku:
|
97
|
-
rake
|
98
|
-
rake
|
99
|
-
|
100
|
-
|
101
|
-
|
71
|
+
rake heroku:apps # Lists configured apps
|
72
|
+
rake heroku:apps:local # Lists configured apps without hitting heroku
|
73
|
+
rake heroku:config # Add config:vars to each application.
|
74
|
+
rake heroku:config:list # Lists config variables as set on Heroku
|
75
|
+
rake heroku:config:list:local # Lists local config variables without setting them
|
76
|
+
rake heroku:config:rack_env # Add proper RACK_ENV to each application
|
77
|
+
rake heroku:console # Opens a remote console
|
78
|
+
rake heroku:create # Creates the Heroku app
|
79
|
+
rake heroku:create_config # Creates an example configuration file
|
80
|
+
rake heroku:db:migrate # Migrates and restarts remote servers
|
81
|
+
rake heroku:db:pull # Pull database from stage to local dev database
|
82
|
+
rake heroku:deploy[commit] # Pushes the given commit, migrates and restarts (default: HEAD)
|
83
|
+
rake heroku:deploy:after # Callback after deploys
|
84
|
+
rake heroku:deploy:before # Callback before deploys
|
85
|
+
rake heroku:deploy:force[commit] # Force-pushes the given commit, migrates and restarts (default: HEAD)
|
86
|
+
rake heroku:logs # Shows the Heroku logs
|
87
|
+
rake heroku:logs:tail # Tail the Heroku logs (requires logging:expanded)
|
88
|
+
rake heroku:maintenance # Enable maintenance mode
|
89
|
+
rake heroku:maintenance_off # Disable maintenance mode
|
90
|
+
rake heroku:maintenance_on # Enable maintenance mode
|
91
|
+
rake heroku:push[commit] # Pushes the given commit (default: HEAD)
|
92
|
+
rake heroku:push:force[commit] # Force-pushes the given commit (default: HEAD)
|
93
|
+
rake heroku:rake[task] # Runs a rake task remotely
|
94
|
+
rake heroku:remotes # Add git remotes for all apps in this project
|
95
|
+
rake heroku:restart # Restarts remote servers
|
96
|
+
rake heroku:share # Adds a collaborator (asks for email)
|
97
|
+
rake heroku:unshare # Removes a collaborator (asks for email)
|
98
|
+
rake heroku:stage:all # Select all Heroku apps for later command
|
99
|
+
|
100
|
+
Frequently used tasks are aliased into the global namespace:
|
101
|
+
|
102
|
+
task :all => 'heroku:stage:all'
|
103
|
+
task :deploy => 'heroku:deploy'
|
104
|
+
task 'deploy:force' => 'heroku:deploy:force'
|
105
|
+
task :before_deploy => 'heroku:deploy:before'
|
106
|
+
task :after_deploy => 'heroku:deploy:after'
|
107
|
+
task :console => 'heroku:console'
|
108
|
+
task :restart => 'heroku:restart'
|
109
|
+
task :migrate => 'heroku:db:migrate'
|
110
|
+
task :logs => 'heroku:logs:default'
|
111
|
+
task 'logs:tail' => 'heroku:logs:tail'
|
102
112
|
|
103
113
|
== Links
|
104
114
|
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# Adding this to your :after_deploy task this will add an environment variable,
|
2
|
+
# in this case, "REVISION", to your Heroku environment with the current revision.
|
3
|
+
task :after_deploy do
|
4
|
+
each_heroku_app do |stage|
|
5
|
+
revision = stage.revision.split.first
|
6
|
+
stage.push_config('REVISION' => revision) if revision
|
7
|
+
end
|
8
|
+
end
|
data/features/config.feature
CHANGED
data/lib/git.rb
CHANGED
@@ -23,17 +23,25 @@ module Git
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
def
|
27
|
-
|
28
|
-
%x{git tag -l '#{glob}'}.split("\n").last
|
26
|
+
def git_parsed_tag(tag)
|
27
|
+
git_rev_parse(git_tag(tag))
|
29
28
|
end
|
30
29
|
|
31
30
|
def git_rev_parse(ref)
|
32
31
|
return nil if ref.nil?
|
33
32
|
%x{git rev-parse #{ref}}.split("\n").first
|
33
|
+
end
|
34
|
+
|
35
|
+
def git_tag(glob)
|
36
|
+
return nil if glob.nil?
|
37
|
+
%x{git tag -l '#{glob}'}.split("\n").last
|
34
38
|
end
|
35
39
|
|
36
|
-
def
|
37
|
-
|
40
|
+
def git_revision(repo)
|
41
|
+
%x{git ls-remote --heads #{repo} master}.split.first
|
42
|
+
end
|
43
|
+
|
44
|
+
def git_named_rev(ref)
|
45
|
+
%x{git name-rev #{ref}}.chomp
|
38
46
|
end
|
39
47
|
end
|
data/lib/heroku_san.rb
CHANGED
data/lib/heroku_san/stage.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
module HerokuSan
|
2
2
|
class Stage
|
3
3
|
attr_reader :name
|
4
|
+
include Git
|
4
5
|
|
5
6
|
def initialize(stage, options = {})
|
6
7
|
@name = stage
|
@@ -8,7 +9,7 @@ module HerokuSan
|
|
8
9
|
end
|
9
10
|
|
10
11
|
def app
|
11
|
-
@options['app']
|
12
|
+
@options['app'] or raise MissingApp, "#{name}: is missing the app: configuration value. I don't know what to access on Heroku."
|
12
13
|
end
|
13
14
|
|
14
15
|
def repo
|
@@ -35,14 +36,28 @@ module HerokuSan
|
|
35
36
|
end
|
36
37
|
end
|
37
38
|
|
39
|
+
def deploy(sha = nil, force = false)
|
40
|
+
sha ||= git_parsed_tag(tag)
|
41
|
+
git_push(sha, repo, force ? %w[--force] : [])
|
42
|
+
end
|
43
|
+
|
38
44
|
def migrate
|
39
45
|
run 'rake', 'db:migrate'
|
40
46
|
sh_heroku "restart"
|
41
47
|
end
|
42
48
|
|
43
|
-
def maintenance(action)
|
44
|
-
|
45
|
-
|
49
|
+
def maintenance(action = nil)
|
50
|
+
if block_given?
|
51
|
+
sh_heroku "maintenance:on"
|
52
|
+
begin
|
53
|
+
yield
|
54
|
+
ensure
|
55
|
+
sh_heroku "maintenance:off"
|
56
|
+
end
|
57
|
+
else
|
58
|
+
raise ArgumentError, "Action #{action.inspect} must be one of (:on, :off)", caller if ![:on, :off].include?(action)
|
59
|
+
sh_heroku "maintenance:#{action}"
|
60
|
+
end
|
46
61
|
end
|
47
62
|
|
48
63
|
def create
|
@@ -60,18 +75,27 @@ module HerokuSan
|
|
60
75
|
def long_config
|
61
76
|
sh_heroku 'config --long'
|
62
77
|
end
|
78
|
+
|
79
|
+
def push_config(options = {})
|
80
|
+
vars = (options == {} ? config : options).map {|var,value| "#{var}=#{Shellwords.escape(value)}"}.join(' ')
|
81
|
+
sh_heroku "config:add #{vars}"
|
82
|
+
end
|
63
83
|
|
64
84
|
def restart
|
65
85
|
sh_heroku 'restart'
|
66
86
|
end
|
67
87
|
|
68
|
-
def logs
|
69
|
-
sh_heroku 'logs'
|
88
|
+
def logs(tail = false)
|
89
|
+
sh_heroku 'logs' + (tail ? ' --tail' : '')
|
90
|
+
end
|
91
|
+
|
92
|
+
def revision
|
93
|
+
git_named_rev(git_revision(repo))
|
70
94
|
end
|
71
95
|
|
72
96
|
private
|
73
97
|
|
74
|
-
def sh_heroku
|
98
|
+
def sh_heroku(command)
|
75
99
|
sh "heroku #{command} --app #{app}"
|
76
100
|
end
|
77
101
|
end
|
data/lib/heroku_san/version.rb
CHANGED
data/lib/tasks.rb
CHANGED
@@ -5,17 +5,18 @@ include Git
|
|
5
5
|
|
6
6
|
@heroku_san.all.each do |stage|
|
7
7
|
desc "Select #{stage} Heroku app for later commands"
|
8
|
-
task stage do
|
8
|
+
task "heroku:stage:#{stage}" do
|
9
9
|
@heroku_san << stage
|
10
10
|
end
|
11
|
-
|
12
|
-
|
13
|
-
desc 'Select all Heroku apps for later command'
|
14
|
-
task :all do
|
15
|
-
@heroku_san << @heroku_san.all
|
11
|
+
task stage => "heroku:stage:#{stage}"
|
16
12
|
end
|
17
13
|
|
18
14
|
namespace :heroku do
|
15
|
+
desc 'Select all Heroku apps for later command'
|
16
|
+
task 'stage:all' do
|
17
|
+
@heroku_san << @heroku_san.all
|
18
|
+
end
|
19
|
+
|
19
20
|
desc "Creates the Heroku app"
|
20
21
|
task :create do
|
21
22
|
each_heroku_app do |stage|
|
@@ -23,7 +24,7 @@ namespace :heroku do
|
|
23
24
|
end
|
24
25
|
end
|
25
26
|
|
26
|
-
desc "Generate the Heroku gems manifest from gem dependencies"
|
27
|
+
#desc "Generate the Heroku gems manifest from gem dependencies"
|
27
28
|
task :gems => 'gems:base' do
|
28
29
|
raise HerokuSan::Deprecated
|
29
30
|
end
|
@@ -35,7 +36,7 @@ namespace :heroku do
|
|
35
36
|
end
|
36
37
|
end
|
37
38
|
|
38
|
-
desc 'Adds a collaborator'
|
39
|
+
desc 'Adds a collaborator (asks for email)'
|
39
40
|
task :share do
|
40
41
|
print "Email address of collaborator to add: "
|
41
42
|
$stdout.flush
|
@@ -45,7 +46,7 @@ namespace :heroku do
|
|
45
46
|
end
|
46
47
|
end
|
47
48
|
|
48
|
-
desc 'Removes a collaborator'
|
49
|
+
desc 'Removes a collaborator (asks for email)'
|
49
50
|
task :unshare do
|
50
51
|
print "Email address of collaborator to remove: "
|
51
52
|
$stdout.flush
|
@@ -58,15 +59,10 @@ namespace :heroku do
|
|
58
59
|
desc 'Lists configured apps'
|
59
60
|
task :apps => :all do
|
60
61
|
each_heroku_app do |stage|
|
62
|
+
rev = stage.revision
|
61
63
|
puts "#{stage.name} is shorthand for the Heroku app #{stage.app} located at:"
|
62
64
|
puts " #{stage.repo}"
|
63
|
-
|
64
|
-
rev = `git ls-remote -h #{stage.repo}`.split(' ').first
|
65
|
-
if rev.blank?
|
66
|
-
puts 'not deployed'
|
67
|
-
else
|
68
|
-
puts `git name-rev #{rev}`
|
69
|
-
end
|
65
|
+
puts " @ #{rev.blank? ? 'not deployed' : rev}"
|
70
66
|
puts
|
71
67
|
end
|
72
68
|
end
|
@@ -83,26 +79,10 @@ namespace :heroku do
|
|
83
79
|
end
|
84
80
|
end
|
85
81
|
|
86
|
-
desc 'Add proper RACK_ENV to each application'
|
87
|
-
task :rack_env => :all do
|
88
|
-
each_heroku_app do |stage|
|
89
|
-
command = "heroku config --app #{stage.app}"
|
90
|
-
puts command
|
91
|
-
config = Hash[`#{command}`.scan(/^(.+?)\s*=>\s*(.+)$/)]
|
92
|
-
if config['RACK_ENV'] != stage.name
|
93
|
-
sh "heroku config:add --app #{stage.app} RACK_ENV=#{stage.name}"
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
82
|
desc 'Add config:vars to each application.'
|
99
83
|
task :config do
|
100
84
|
each_heroku_app do |stage|
|
101
|
-
|
102
|
-
stage.config.each do |var, value|
|
103
|
-
command += " #{var}=#{value}"
|
104
|
-
end
|
105
|
-
sh(command)
|
85
|
+
stage.push_config
|
106
86
|
end
|
107
87
|
end
|
108
88
|
|
@@ -122,6 +102,18 @@ namespace :heroku do
|
|
122
102
|
end
|
123
103
|
|
124
104
|
namespace :config do
|
105
|
+
desc 'Add proper RACK_ENV to each application'
|
106
|
+
task :rack_env => :all do
|
107
|
+
each_heroku_app do |stage|
|
108
|
+
command = "heroku config --app #{stage.app}"
|
109
|
+
puts command
|
110
|
+
config = Hash[`#{command}`.scan(/^(.+?)\s*=>\s*(.+)$/)]
|
111
|
+
if config['RACK_ENV'] != stage.name
|
112
|
+
stage.push_config RACK_ENV: stage.name
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
125
117
|
desc "Lists config variables as set on Heroku"
|
126
118
|
task :list do
|
127
119
|
each_heroku_app do |stage|
|
@@ -152,7 +144,7 @@ namespace :heroku do
|
|
152
144
|
desc "Pushes the given commit (default: HEAD)"
|
153
145
|
task :push, :commit do |t, args|
|
154
146
|
each_heroku_app do |stage|
|
155
|
-
|
147
|
+
stage.deploy(args[:commit])
|
156
148
|
end
|
157
149
|
end
|
158
150
|
|
@@ -160,7 +152,7 @@ namespace :heroku do
|
|
160
152
|
desc "Force-pushes the given commit (default: HEAD)"
|
161
153
|
task :force, :commit do |t, args|
|
162
154
|
each_heroku_app do |stage|
|
163
|
-
|
155
|
+
stage.deploy(args[:commit], :force)
|
164
156
|
end
|
165
157
|
end
|
166
158
|
end
|
@@ -185,89 +177,122 @@ namespace :heroku do
|
|
185
177
|
stage.maintenance :off
|
186
178
|
end
|
187
179
|
end
|
188
|
-
end
|
189
|
-
|
190
|
-
desc "Pushes the given commit, migrates and restarts (default: HEAD)"
|
191
|
-
task :deploy, [:commit] => [:before_deploy] do |t, args|
|
192
|
-
each_heroku_app do |stage|
|
193
|
-
git_push(args[:commit] || git_parsed_tag(stage.tag), stage.repo)
|
194
|
-
stage.migrate
|
195
|
-
end
|
196
|
-
Rake::Task[:after_deploy].execute
|
197
|
-
end
|
198
180
|
|
199
|
-
|
200
|
-
|
201
|
-
task :force, [:commit] => [:before_deploy] do |t, args|
|
181
|
+
desc "Pushes the given commit, migrates and restarts (default: HEAD)"
|
182
|
+
task :deploy, [:commit] => [:before_deploy] do |t, args|
|
202
183
|
each_heroku_app do |stage|
|
203
|
-
|
184
|
+
stage.deploy(args[:commit])
|
204
185
|
stage.migrate
|
205
186
|
end
|
206
187
|
Rake::Task[:after_deploy].execute
|
207
188
|
end
|
208
|
-
end
|
209
189
|
|
210
|
-
|
211
|
-
|
212
|
-
|
190
|
+
namespace :deploy do
|
191
|
+
desc "Force-pushes the given commit, migrates and restarts (default: HEAD)"
|
192
|
+
task :force, [:commit] => [:before_deploy] do |t, args|
|
193
|
+
each_heroku_app do |stage|
|
194
|
+
stage.deploy(args[:commit], :force)
|
195
|
+
stage.migrate
|
196
|
+
end
|
197
|
+
Rake::Task[:after_deploy].execute
|
198
|
+
end
|
213
199
|
|
214
|
-
desc "Callback before deploys"
|
215
|
-
task :
|
216
|
-
end
|
200
|
+
desc "Callback before deploys"
|
201
|
+
task :before do
|
202
|
+
end
|
217
203
|
|
218
|
-
desc "Callback after deploys"
|
219
|
-
task :
|
220
|
-
end
|
204
|
+
desc "Callback after deploys"
|
205
|
+
task :after do
|
206
|
+
end
|
221
207
|
|
222
|
-
|
223
|
-
task :capture do
|
224
|
-
raise Deprecated
|
225
|
-
end
|
208
|
+
end
|
226
209
|
|
227
|
-
|
228
|
-
|
229
|
-
each_heroku_app do |stage|
|
230
|
-
stage.run 'console'
|
210
|
+
task :force_deploy do
|
211
|
+
raise HerokuSan::Deprecated
|
231
212
|
end
|
232
|
-
end
|
233
213
|
|
234
|
-
desc "
|
235
|
-
task :
|
236
|
-
|
237
|
-
stage.restart
|
214
|
+
#desc "Captures a bundle on Heroku"
|
215
|
+
task :capture do
|
216
|
+
raise HerokuSan::Deprecated
|
238
217
|
end
|
239
|
-
end
|
240
218
|
|
241
|
-
desc "
|
242
|
-
task :
|
243
|
-
|
244
|
-
|
219
|
+
desc "Opens a remote console"
|
220
|
+
task :console do
|
221
|
+
each_heroku_app do |stage|
|
222
|
+
stage.run 'console'
|
223
|
+
end
|
245
224
|
end
|
246
|
-
end
|
247
225
|
|
248
|
-
desc "
|
249
|
-
task :
|
250
|
-
|
251
|
-
|
226
|
+
desc "Restarts remote servers"
|
227
|
+
task :restart do
|
228
|
+
each_heroku_app do |stage|
|
229
|
+
stage.restart
|
230
|
+
end
|
252
231
|
end
|
253
|
-
end
|
254
232
|
|
255
|
-
namespace :
|
256
|
-
|
233
|
+
namespace :logs do
|
234
|
+
task :default do
|
235
|
+
each_heroku_app do |stage|
|
236
|
+
stage.logs
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
desc "Tail the Heroku logs (requires logging:expanded)"
|
241
|
+
task :tail do
|
242
|
+
each_heroku_app do |stage|
|
243
|
+
stage.logs(:tail)
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
desc "Shows the Heroku logs"
|
249
|
+
task :logs => 'logs:default'
|
250
|
+
|
251
|
+
namespace :db do
|
252
|
+
desc "Migrates and restarts remote servers"
|
253
|
+
task :migrate do
|
254
|
+
each_heroku_app do |stage|
|
255
|
+
stage.migrate
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
desc "Pull database from stage to local dev database"
|
260
|
+
task :pull do
|
261
|
+
each_heroku_app do |stage|
|
262
|
+
sh "heroku pgdumps:capture --app #{stage.app}"
|
263
|
+
dump = `heroku pgdumps --app #{stage.app}`.split("\n").last.split(" ").first
|
264
|
+
sh "mkdir -p #{Rails.root}/db/dumps"
|
265
|
+
file = "#{Rails.root}/db/dumps/#{dump}.sql.gz"
|
266
|
+
url = `heroku pgdumps:url --app #{stage.app} #{dump}`.chomp
|
267
|
+
sh "wget", url, "-O", file
|
268
|
+
sh "rake db:drop db:create"
|
269
|
+
sh "gunzip -c #{file} | #{Rails.root}/script/dbconsole"
|
270
|
+
sh "rake jobs:clear"
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
desc "Run a bash shell on Heroku"
|
276
|
+
task :shell do
|
257
277
|
each_heroku_app do |stage|
|
258
|
-
|
259
|
-
dump = `heroku pgdumps --app #{stage.app}`.split("\n").last.split(" ").first
|
260
|
-
sh "mkdir -p #{Rails.root}/db/dumps"
|
261
|
-
file = "#{Rails.root}/db/dumps/#{dump}.sql.gz"
|
262
|
-
url = `heroku pgdumps:url --app #{stage.app} #{dump}`.chomp
|
263
|
-
sh "wget", url, "-O", file
|
264
|
-
sh "rake db:drop db:create"
|
265
|
-
sh "gunzip -c #{file} | #{Rails.root}/script/dbconsole"
|
266
|
-
sh "rake jobs:clear"
|
278
|
+
stage.run 'bash'
|
267
279
|
end
|
268
280
|
end
|
269
281
|
end
|
270
282
|
|
283
|
+
task :all => 'heroku:stage:all'
|
284
|
+
task :deploy => 'heroku:deploy'
|
285
|
+
task 'deploy:force' => 'heroku:deploy:force'
|
286
|
+
task :before_deploy => 'heroku:deploy:before'
|
287
|
+
task :after_deploy => 'heroku:deploy:after'
|
288
|
+
task :console => 'heroku:console'
|
289
|
+
task :restart => 'heroku:restart'
|
290
|
+
task :migrate => 'heroku:db:migrate'
|
291
|
+
task :logs => 'heroku:logs:default'
|
292
|
+
task 'logs:tail' => 'heroku:logs:tail'
|
293
|
+
task 'heroku:rack_env' => 'heroku:config:rack_env'
|
294
|
+
task :shell => 'heroku:shell'
|
295
|
+
|
271
296
|
def each_heroku_app(&block)
|
272
297
|
@heroku_san.each_app(&block)
|
273
298
|
puts
|
data/spec/git_spec.rb
CHANGED
@@ -52,4 +52,23 @@ describe GitTest do
|
|
52
52
|
subject.git_rev_parse(nil).should == nil
|
53
53
|
end
|
54
54
|
end
|
55
|
+
|
56
|
+
describe "#git_revision" do
|
57
|
+
it "returns the current revision of the repository (on Heroku)" do
|
58
|
+
subject.should_receive("`").with("git ls-remote --heads staging master") { "sha\n" }
|
59
|
+
subject.git_revision('staging').should == 'sha'
|
60
|
+
end
|
61
|
+
|
62
|
+
it "returns nil if there is no revision (i.e. not deployed yet)" do
|
63
|
+
subject.should_receive("`").with("git ls-remote --heads staging master") { "\n" }
|
64
|
+
subject.git_revision('staging').should == nil
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "#git_named_rev" do
|
69
|
+
it "returns symbolic names for given rev" do
|
70
|
+
subject.should_receive("`").with("git name-rev sha") {"sha production/123456\n"}
|
71
|
+
subject.git_named_rev('sha').should == 'sha production/123456'
|
72
|
+
end
|
73
|
+
end
|
55
74
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe HerokuSan::Stage do
|
4
|
+
include Git
|
4
5
|
subject { HerokuSan::Stage.new('production', {"app" => "awesomeapp", "stack" => "bamboo-ree-1.8.7"})}
|
5
6
|
|
6
7
|
context "initializes" do
|
@@ -19,6 +20,16 @@ describe HerokuSan::Stage do
|
|
19
20
|
its(:repo) { should == 'git@heroku.com:awesomeapp-demo.git' }
|
20
21
|
end
|
21
22
|
|
23
|
+
describe "#app" do
|
24
|
+
its(:app) { should == 'awesomeapp'}
|
25
|
+
context "blank app" do
|
26
|
+
subject { HerokuSan::Stage.new('production') }
|
27
|
+
it "should raise an error" do
|
28
|
+
expect { subject.app }.to raise_error(HerokuSan::MissingApp, /production: is missing the app: configuration value\./)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
22
33
|
context "celadon cedar stack has a different API" do
|
23
34
|
describe "#stack" do
|
24
35
|
it "returns the name of the stack from Heroku" do
|
@@ -54,6 +65,28 @@ EOT
|
|
54
65
|
end
|
55
66
|
end
|
56
67
|
|
68
|
+
describe "#deploy" do
|
69
|
+
it "deploys to heroku" do
|
70
|
+
subject.should_receive(:git_push).with(git_parsed_tag(subject.tag), subject.repo, [])
|
71
|
+
subject.deploy
|
72
|
+
end
|
73
|
+
|
74
|
+
it "deploys with a custom sha" do
|
75
|
+
subject.should_receive(:git_push).with('deadbeef', subject.repo, [])
|
76
|
+
subject.deploy('deadbeef')
|
77
|
+
end
|
78
|
+
|
79
|
+
it "deploys with --force" do
|
80
|
+
subject.should_receive(:git_push).with(git_parsed_tag(subject.tag), subject.repo, %w[--force])
|
81
|
+
subject.deploy(nil, :force)
|
82
|
+
end
|
83
|
+
|
84
|
+
it "deploys with a custom sha & --force" do
|
85
|
+
subject.should_receive(:git_push).with('deadbeef', subject.repo, %w[--force])
|
86
|
+
subject.deploy('deadbeef', :force)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
57
90
|
describe "#migrate" do
|
58
91
|
it "runs rake db:migrate" do
|
59
92
|
subject.should_receive(:sh).with("heroku run:rake db:migrate --app awesomeapp")
|
@@ -62,7 +95,7 @@ EOT
|
|
62
95
|
end
|
63
96
|
end
|
64
97
|
|
65
|
-
describe "#maintenance" do
|
98
|
+
describe "#maintenance" do
|
66
99
|
it ":on" do
|
67
100
|
subject.should_receive(:sh).with("heroku maintenance:on --app awesomeapp")
|
68
101
|
subject.maintenance :on
|
@@ -78,6 +111,27 @@ EOT
|
|
78
111
|
subject.maintenance :busy
|
79
112
|
end.to raise_error ArgumentError, "Action #{:busy.inspect} must be one of (:on, :off)"
|
80
113
|
end
|
114
|
+
|
115
|
+
context "with a block" do
|
116
|
+
it "wraps it in a maitenance mode" do
|
117
|
+
subject.should_receive(:sh).with("heroku maintenance:on --app awesomeapp")
|
118
|
+
reactor = mock("Reactor"); reactor.should_receive(:scram).with(:now)
|
119
|
+
subject.should_receive(:sh).with("heroku maintenance:off --app awesomeapp")
|
120
|
+
subject.maintenance do
|
121
|
+
reactor.scram(:now)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
it "ensures that maintenance mode is turned off" do
|
125
|
+
subject.should_receive(:sh).with("heroku maintenance:on --app awesomeapp")
|
126
|
+
reactor = mock("Reactor"); reactor.should_receive(:scram).with(:now).and_raise(RuntimeError)
|
127
|
+
subject.should_receive(:sh).with("heroku maintenance:off --app awesomeapp")
|
128
|
+
expect {
|
129
|
+
subject.maintenance do
|
130
|
+
reactor.scram(:now)
|
131
|
+
end
|
132
|
+
}.to raise_error
|
133
|
+
end
|
134
|
+
end
|
81
135
|
end
|
82
136
|
|
83
137
|
describe "#create" do
|
@@ -133,6 +187,39 @@ EOT
|
|
133
187
|
subject.should_receive(:sh).with("heroku logs --app awesomeapp")
|
134
188
|
subject.logs
|
135
189
|
end
|
190
|
+
it "tails log files" do
|
191
|
+
subject.should_receive(:sh).with("heroku logs --tail --app awesomeapp")
|
192
|
+
subject.logs(:tail)
|
193
|
+
end
|
136
194
|
end
|
137
195
|
|
196
|
+
describe "#push_config" do
|
197
|
+
it "updates the configuration settings on Heroku" do
|
198
|
+
subject = HerokuSan::Stage.new('test', {"app" => "awesomeapp", "config" => {FOO: 'bar', DOG: 'emu'}})
|
199
|
+
subject.should_receive(:sh).with("heroku config:add FOO=bar DOG=emu --app awesomeapp")
|
200
|
+
subject.push_config
|
201
|
+
end
|
202
|
+
it "properly escapes variables" do
|
203
|
+
subject = HerokuSan::Stage.new('test', {"app" => "awesomeapp", "config" => {FOO: ' bar\emu bat zebra '}})
|
204
|
+
subject.should_receive(:sh).with("heroku config:add FOO=#{Shellwords.escape(' bar\emu bat zebra ')} --app awesomeapp")
|
205
|
+
subject.push_config
|
206
|
+
end
|
207
|
+
it "pushes the options hash" do
|
208
|
+
subject.should_receive(:sh).with("heroku config:add RACK_ENV=magic --app awesomeapp")
|
209
|
+
subject.push_config(RACK_ENV: 'magic')
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
describe "#revision" do
|
214
|
+
it "returns the named remote revision for the stage" do
|
215
|
+
subject.should_receive(:git_revision).with(subject.repo) {"sha"}
|
216
|
+
subject.should_receive(:git_named_rev).with('sha') {"sha production/123456"}
|
217
|
+
subject.revision.should == 'sha production/123456'
|
218
|
+
end
|
219
|
+
it "returns nil if the stage has never been deployed" do
|
220
|
+
subject.should_receive(:git_revision).with(subject.repo) {nil}
|
221
|
+
subject.should_receive(:git_named_rev).with(nil) {''}
|
222
|
+
subject.revision.should == ''
|
223
|
+
end
|
224
|
+
end
|
138
225
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: heroku_san
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -12,11 +12,11 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2012-03-
|
15
|
+
date: 2012-03-06 00:00:00.000000000Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: rails
|
19
|
-
requirement: &
|
19
|
+
requirement: &2153413220 !ruby/object:Gem::Requirement
|
20
20
|
none: false
|
21
21
|
requirements:
|
22
22
|
- - ! '>='
|
@@ -24,10 +24,10 @@ dependencies:
|
|
24
24
|
version: '2'
|
25
25
|
type: :runtime
|
26
26
|
prerelease: false
|
27
|
-
version_requirements: *
|
27
|
+
version_requirements: *2153413220
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: heroku
|
30
|
-
requirement: &
|
30
|
+
requirement: &2153412680 !ruby/object:Gem::Requirement
|
31
31
|
none: false
|
32
32
|
requirements:
|
33
33
|
- - ! '>='
|
@@ -35,10 +35,10 @@ dependencies:
|
|
35
35
|
version: '2'
|
36
36
|
type: :runtime
|
37
37
|
prerelease: false
|
38
|
-
version_requirements: *
|
38
|
+
version_requirements: *2153412680
|
39
39
|
- !ruby/object:Gem::Dependency
|
40
40
|
name: rake
|
41
|
-
requirement: &
|
41
|
+
requirement: &2153412280 !ruby/object:Gem::Requirement
|
42
42
|
none: false
|
43
43
|
requirements:
|
44
44
|
- - ! '>='
|
@@ -46,10 +46,10 @@ dependencies:
|
|
46
46
|
version: '0'
|
47
47
|
type: :runtime
|
48
48
|
prerelease: false
|
49
|
-
version_requirements: *
|
49
|
+
version_requirements: *2153412280
|
50
50
|
- !ruby/object:Gem::Dependency
|
51
51
|
name: aruba
|
52
|
-
requirement: &
|
52
|
+
requirement: &2153411640 !ruby/object:Gem::Requirement
|
53
53
|
none: false
|
54
54
|
requirements:
|
55
55
|
- - ! '>='
|
@@ -57,10 +57,10 @@ dependencies:
|
|
57
57
|
version: '0'
|
58
58
|
type: :development
|
59
59
|
prerelease: false
|
60
|
-
version_requirements: *
|
60
|
+
version_requirements: *2153411640
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
62
|
name: cucumber
|
63
|
-
requirement: &
|
63
|
+
requirement: &2153411060 !ruby/object:Gem::Requirement
|
64
64
|
none: false
|
65
65
|
requirements:
|
66
66
|
- - ! '>='
|
@@ -68,10 +68,10 @@ dependencies:
|
|
68
68
|
version: '0'
|
69
69
|
type: :development
|
70
70
|
prerelease: false
|
71
|
-
version_requirements: *
|
71
|
+
version_requirements: *2153411060
|
72
72
|
- !ruby/object:Gem::Dependency
|
73
73
|
name: rake
|
74
|
-
requirement: &
|
74
|
+
requirement: &2153410400 !ruby/object:Gem::Requirement
|
75
75
|
none: false
|
76
76
|
requirements:
|
77
77
|
- - ! '>='
|
@@ -79,10 +79,10 @@ dependencies:
|
|
79
79
|
version: '0'
|
80
80
|
type: :development
|
81
81
|
prerelease: false
|
82
|
-
version_requirements: *
|
82
|
+
version_requirements: *2153410400
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: bundler
|
85
|
-
requirement: &
|
85
|
+
requirement: &2153409500 !ruby/object:Gem::Requirement
|
86
86
|
none: false
|
87
87
|
requirements:
|
88
88
|
- - ~>
|
@@ -90,7 +90,7 @@ dependencies:
|
|
90
90
|
version: '1.0'
|
91
91
|
type: :development
|
92
92
|
prerelease: false
|
93
|
-
version_requirements: *
|
93
|
+
version_requirements: *2153409500
|
94
94
|
description: Manage multiple Heroku instances/apps for a single Rails app using Rake
|
95
95
|
email: elijah.miller@gmail.com
|
96
96
|
executables: []
|
@@ -101,6 +101,7 @@ files:
|
|
101
101
|
- .gitignore
|
102
102
|
- .gitmodules
|
103
103
|
- .rvmrc
|
104
|
+
- CHANGELOG.md
|
104
105
|
- Gemfile
|
105
106
|
- LICENSE
|
106
107
|
- README.rdoc
|
@@ -108,6 +109,7 @@ files:
|
|
108
109
|
- autotest/discover.rb
|
109
110
|
- cucumber.yml
|
110
111
|
- examples/auto_tagger.rake
|
112
|
+
- examples/push_revision.rake
|
111
113
|
- features/config.feature
|
112
114
|
- features/extended-config.feature
|
113
115
|
- features/remote.feature
|