heroku_tasks 0.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/README.rdoc +67 -0
- data/lib/generators/heroku_tasks/config/config_generator.rb +16 -0
- data/lib/generators/heroku_tasks/config/templates/heroku.yml +4 -0
- data/lib/heroku_tasks.rb +20 -0
- data/lib/heroku_tasks/railtie.rb +10 -0
- data/lib/heroku_tasks/version.rb +3 -0
- data/lib/tasks/deploy.rake +158 -0
- metadata +91 -0
data/README.rdoc
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
= Installation
|
2
|
+
|
3
|
+
Add it to your Gemfile (inside development group)
|
4
|
+
|
5
|
+
gem 'heroku_tasks', :git => 'git://github.com/thibaudgg/heroku_tasks.git'
|
6
|
+
|
7
|
+
= Configuration
|
8
|
+
|
9
|
+
Setup staging/production branch (here from remote)
|
10
|
+
|
11
|
+
git checkout -t origin/production
|
12
|
+
git checkout -t origin/staging
|
13
|
+
|
14
|
+
Create config/heroku.yml file and edit it
|
15
|
+
|
16
|
+
rails generate heroku_tasks:config
|
17
|
+
|
18
|
+
= Deploy procedure
|
19
|
+
|
20
|
+
Merge your last work in staging branch
|
21
|
+
|
22
|
+
git checkout staging
|
23
|
+
git pull origin staging
|
24
|
+
git merge master
|
25
|
+
|
26
|
+
Regenerate your assets if you're using {Jammit}[http://documentcloud.github.com/jammit/] (and you should)
|
27
|
+
|
28
|
+
rake deploy:assets
|
29
|
+
|
30
|
+
Push your code to staging heroku app
|
31
|
+
|
32
|
+
rake deploy:staging
|
33
|
+
or
|
34
|
+
rake deploy:staging:migrations
|
35
|
+
|
36
|
+
If your staging app is still alive
|
37
|
+
|
38
|
+
git checkout production
|
39
|
+
git pull origin production
|
40
|
+
git merge staging
|
41
|
+
|
42
|
+
Activate maintenance page on production and wait for it (Optional, ie. with migrations)
|
43
|
+
|
44
|
+
heroku maintenance:on --app production_app
|
45
|
+
|
46
|
+
Push your code to production app
|
47
|
+
|
48
|
+
rake deploy:production
|
49
|
+
or
|
50
|
+
rake deploy:production:migrations
|
51
|
+
|
52
|
+
Don't forget to remove maintenance page if needed
|
53
|
+
|
54
|
+
heroku maintenance:off --app production_app
|
55
|
+
|
56
|
+
Back to work (after some rest!)
|
57
|
+
|
58
|
+
git checkout master
|
59
|
+
git merge production
|
60
|
+
|
61
|
+
= Rollback
|
62
|
+
|
63
|
+
If you met any problems
|
64
|
+
|
65
|
+
rake deploy:staging:rollback
|
66
|
+
or
|
67
|
+
rake deploy:production:rollback
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module HerokuTasks
|
2
|
+
module Generators
|
3
|
+
class ConfigGenerator < Rails::Generators::Base
|
4
|
+
desc "Creates a HerokuTasks configuration file at config/heroku.yml"
|
5
|
+
|
6
|
+
def self.source_root
|
7
|
+
@source_root ||= File.expand_path(File.join(File.dirname(__FILE__), 'templates'))
|
8
|
+
end
|
9
|
+
|
10
|
+
def create_config_file
|
11
|
+
template 'heroku.yml', File.join('config', "heroku.yml")
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/heroku_tasks.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module HerokuTasks
|
2
|
+
require 'heroku_tasks/railtie' if defined?(Rails)
|
3
|
+
|
4
|
+
class << self
|
5
|
+
|
6
|
+
def method_missing(name)
|
7
|
+
yml[name.to_s]
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def yml
|
13
|
+
config_path = Rails.root.join('config', 'heroku.yml')
|
14
|
+
@yml_options ||= YAML::load_file(config_path)
|
15
|
+
rescue
|
16
|
+
raise "\nconfig/heroku.yml not found. To generate one run: rails generate heroku_tasks:config\n"
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
namespace :deploy do
|
2
|
+
|
3
|
+
desc "Prepare jammit assets before deploy"
|
4
|
+
task :assets do
|
5
|
+
system "bundle exec jammit -u #{HerokuTasks.production_url} -f"
|
6
|
+
|
7
|
+
Dir.glob("public/assets/*.css").each do |file|
|
8
|
+
puts file
|
9
|
+
buffer = File.new(file,'r').read.gsub(/@media screen and\(/,"@media screen and (")
|
10
|
+
File.open(file,'w') {|fw| fw.write(buffer)}
|
11
|
+
end
|
12
|
+
|
13
|
+
system "git add public/assets/*"
|
14
|
+
system "git commit public/assets/* -m 'Updated assets before deploy'"
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "Heroku staging (#{HerokuTasks.staging}) deploy"
|
18
|
+
task :staging => [:set_staging_app, :push, :restart, :tag]
|
19
|
+
|
20
|
+
namespace :staging do
|
21
|
+
desc "Heroku staging (#{HerokuTasks.staging}) deploy with migration (and copy production db)"
|
22
|
+
task :migrations => [:set_staging_app, :push, :copy_production_db, :migrate, :restart, :tag]
|
23
|
+
desc "Heroku staging (#{HerokuTasks.staging}) rollback"
|
24
|
+
task :rollback => [:set_staging_app, :rollback, :restart]
|
25
|
+
end
|
26
|
+
|
27
|
+
desc "Heroku production (#{HerokuTasks.production}) deploy"
|
28
|
+
task :production => [:set_production_app, :push, :restart, :tag]
|
29
|
+
|
30
|
+
namespace :production do
|
31
|
+
desc "Heroku production (#{HerokuTasks.staging}) deploy with migration"
|
32
|
+
task :migrations => [:set_production_app, :push, :migrate, :restart, :tag]
|
33
|
+
desc "Heroku production (#{HerokuTasks.staging}) rollback"
|
34
|
+
task :rollback => [:set_production_app, :rollback, :restart]
|
35
|
+
end
|
36
|
+
|
37
|
+
# =======================
|
38
|
+
# = Don't call directly =
|
39
|
+
# =======================
|
40
|
+
|
41
|
+
task :set_staging_app do
|
42
|
+
APP = HerokuTasks.staging
|
43
|
+
TARGET = 'staging'
|
44
|
+
end
|
45
|
+
task :set_production_app do
|
46
|
+
APP = HerokuTasks.production
|
47
|
+
TARGET = 'production'
|
48
|
+
end
|
49
|
+
|
50
|
+
task :push do
|
51
|
+
timed do
|
52
|
+
puts "\nDeploying #{TARGET}'s branch to #{APP} on heroku ..."
|
53
|
+
system "git push git@heroku.com:#{APP}.git #{TARGET}:master"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
task :restart do
|
58
|
+
timed do
|
59
|
+
puts "\nRestarting #{app_and_target} servers ..."
|
60
|
+
system "heroku restart --app #{APP}"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
task :tag do
|
65
|
+
tag_and_push_release("#{prefix}#{normalized_date}")
|
66
|
+
end
|
67
|
+
|
68
|
+
task :migrate do
|
69
|
+
timed do
|
70
|
+
puts "\nRunning database migrations for #{app_and_target} ..."
|
71
|
+
system "heroku rake db:migrate --app #{APP}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
task :copy_production_db do
|
76
|
+
timed do
|
77
|
+
puts "\nCopying production database for #{app_and_target} ..."
|
78
|
+
system "heroku db:pull sqlite://backup.db --app #{HerokuTasks.production}"
|
79
|
+
system "heroku db:push sqlite://backup.db --app #{APP}"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
task :rollback do
|
84
|
+
releases = `git tag`.split("\n").select { |t| t[0..prefix.length-1] == prefix }.sort
|
85
|
+
|
86
|
+
if releases.length >= 2
|
87
|
+
current_release = releases.last
|
88
|
+
previous_release = releases[-2]
|
89
|
+
|
90
|
+
started_at = Time.now.utc
|
91
|
+
puts "\nRolling back to '#{previous_release}' ..."
|
92
|
+
|
93
|
+
puts "\nChecking out '#{previous_release}' in a new branch on local git repo ..."
|
94
|
+
system "git checkout #{previous_release}"
|
95
|
+
system "git checkout -b #{previous_release}"
|
96
|
+
|
97
|
+
puts "\nRemoving tagged version '#{previous_release}' (now transformed in branch) ..."
|
98
|
+
delete_tagged_version(previous_release)
|
99
|
+
|
100
|
+
puts "\nPushing '#{previous_release}' to #{APP} on heroku/master ..."
|
101
|
+
system "git push git@heroku.com:#{APP}.git +#{previous_release}:master --force"
|
102
|
+
puts "Done"
|
103
|
+
|
104
|
+
puts "\nDeleting rollbacked release '#{current_release}' ..."
|
105
|
+
delete_tagged_version(current_release)
|
106
|
+
|
107
|
+
puts "\nRetagging release '#{previous_release}' ..."
|
108
|
+
tag_and_push_release(previous_release)
|
109
|
+
|
110
|
+
puts "\nTurning local repo checked out on master ..."
|
111
|
+
system "git checkout master"
|
112
|
+
puts "All done! Rolled back to '#{previous_release}' in #{Time.now.utc - started_at} seconds!"
|
113
|
+
else
|
114
|
+
puts "\nCan't roll back! You need at least 2 release to be able to rollback the last release!"
|
115
|
+
puts releases
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def prefix
|
120
|
+
"#{APP}_#{TARGET}_release-"
|
121
|
+
end
|
122
|
+
|
123
|
+
def app_and_target
|
124
|
+
"#{APP} (#{TARGET})"
|
125
|
+
end
|
126
|
+
|
127
|
+
def delete_tagged_version(release_name)
|
128
|
+
timed do
|
129
|
+
system "git tag -d #{release_name}"
|
130
|
+
system "git push git@heroku.com:#{APP}.git :refs/tags/#{release_name}"
|
131
|
+
system "git push #{HerokuTasks.git_repo} :refs/tags/#{release_name}"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def tag_and_push_release(release_name)
|
136
|
+
timed do
|
137
|
+
puts "\nTagging release as '#{release_name}'"
|
138
|
+
system "git tag -a #{release_name} -m \"Heroku's tagged release\""
|
139
|
+
system "git push --tags git@heroku.com:#{APP}.git"
|
140
|
+
system "git push --tags #{HerokuTasks.git_repo}"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def normalized_date
|
145
|
+
Time.now.utc.strftime("%Y%m%d%H%M%S")
|
146
|
+
end
|
147
|
+
|
148
|
+
def timed(&block)
|
149
|
+
if block_given?
|
150
|
+
start_time = Time.now.utc
|
151
|
+
yield
|
152
|
+
print "\tDone in #{Time.now.utc - start_time}s!\n\n"
|
153
|
+
else
|
154
|
+
print "\n\nYou must pass a block to this method!\n\n"
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
metadata
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: heroku_tasks
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Thibaud Guillaume-Gentil
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-08-31 00:00:00 +02:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: bundler
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 23
|
30
|
+
segments:
|
31
|
+
- 1
|
32
|
+
- 0
|
33
|
+
- 0
|
34
|
+
version: 1.0.0
|
35
|
+
type: :development
|
36
|
+
version_requirements: *id001
|
37
|
+
description: Bundle of rake tasks to manage staging/production heroku deploy.
|
38
|
+
email:
|
39
|
+
- thibaud@thibaud.me
|
40
|
+
executables: []
|
41
|
+
|
42
|
+
extensions: []
|
43
|
+
|
44
|
+
extra_rdoc_files: []
|
45
|
+
|
46
|
+
files:
|
47
|
+
- lib/generators/heroku_tasks/config/config_generator.rb
|
48
|
+
- lib/generators/heroku_tasks/config/templates/heroku.yml
|
49
|
+
- lib/heroku_tasks/railtie.rb
|
50
|
+
- lib/heroku_tasks/version.rb
|
51
|
+
- lib/heroku_tasks.rb
|
52
|
+
- lib/tasks/deploy.rake
|
53
|
+
- README.rdoc
|
54
|
+
has_rdoc: true
|
55
|
+
homepage: http://rubygems.org/gems/heroku_tasks
|
56
|
+
licenses: []
|
57
|
+
|
58
|
+
post_install_message:
|
59
|
+
rdoc_options: []
|
60
|
+
|
61
|
+
require_paths:
|
62
|
+
- lib
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
hash: 3
|
69
|
+
segments:
|
70
|
+
- 0
|
71
|
+
version: "0"
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
hash: 23
|
78
|
+
segments:
|
79
|
+
- 1
|
80
|
+
- 3
|
81
|
+
- 6
|
82
|
+
version: 1.3.6
|
83
|
+
requirements: []
|
84
|
+
|
85
|
+
rubyforge_project: heroku_tasks
|
86
|
+
rubygems_version: 1.3.7
|
87
|
+
signing_key:
|
88
|
+
specification_version: 3
|
89
|
+
summary: Bundle of rake tasks to manage staging/production heroku deploy
|
90
|
+
test_files: []
|
91
|
+
|