This repository has been archived by the owner on Jun 8, 2019. It is now read-only.
/
deployer.rb
196 lines (165 loc) · 4.63 KB
/
deployer.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
require 'thor/shell'
require 'rake'
module Kumade
class Deployer < Thor::Shell::Color
def pre_deploy
ensure_clean_git
ensure_rake_passes
package_assets
git_push('origin')
end
def deploy_to(environment)
string_environment = environment.to_s
ensure_heroku_remote_exists_for(string_environment)
pre_deploy
git_force_push(string_environment)
heroku_migrate(string_environment)
end
def git_push(remote)
run_or_error("git push #{remote} master",
"Failed to push master -> #{remote}")
success("Pushed master -> #{remote}")
end
def git_force_push(remote)
run_or_error("git push -f #{remote} master",
"Failed to force push master -> #{remote}")
success("Force pushed master -> #{remote}")
end
def heroku_migrate(environment)
app = Kumade.app_for(environment)
run("bundle exec heroku rake db:migrate --app #{app}")
success("Migrated #{app}")
end
def ensure_clean_git
if git_dirty?
error("Cannot deploy: repo is not clean.")
else
success("Git repo is clean")
end
end
def ensure_rake_passes
if default_task_exists?
if rake_succeeded?
success("Rake passed")
else
error("Cannot deploy: tests did not pass")
end
end
end
def package_assets
package_with_jammit if jammit_installed?
package_with_more if more_installed?
end
def package_with_jammit
begin
Jammit.package!
if git_dirty?
success("Packaged assets with Jammit")
git_add_and_commit_all_assets_in(absolute_assets_path)
end
rescue => jammit_error
error("Error: #{jammit_error.class}: #{jammit_error.message}")
end
end
def package_with_more
begin
Rake::Task['more:generate'].invoke
if git_dirty?
success("Packaged assets with More")
git_add_and_commit_all_assets_in(more_assets_path)
end
rescue => more_error
error("Error: #{more_error.class}: #{more_error.message}")
end
end
def git_add_and_commit_all_assets_in(dir)
announce "Committing assets"
run_or_error("git add #{dir} && git commit -m 'Assets'",
"Cannot deploy: couldn't commit assets")
success("Added and committed all assets")
end
def git_add_and_commit_all_more_assets
announce "Committing assets"
run_or_error("git add #{more_assets_path} && git commit -m 'Assets'",
"Cannot deploy: couldn't commit assets")
end
def absolute_assets_path
File.join(Jammit::PUBLIC_ROOT, Jammit.package_path)
end
def more_assets_path
File.join('public', ::Less::More.destination_path)
end
def jammit_installed?
@jammit_installed ||=
(defined?(Jammit) ||
begin
require 'jammit'
rescue LoadError
false
end)
end
def more_installed?
@more_installed ||=
(defined?(Less::More) ||
begin
require 'less/more'
rescue LoadError
false
end)
end
def default_task_exists?
Rake::Task.task_defined?('default')
end
def rake_succeeded?
begin
Rake::Task[:default].invoke
rescue
false
end
end
def git_dirty?
git_changed = `git status --short 2> /dev/null | tail -n1`
dirty = git_changed.size > 0
end
def run(command)
announce "+ #{command}"
announce "- #{system command}"
$?.success?
end
def run_or_error(command, error_message)
unless run(command)
error(error_message)
end
end
def announce(message)
say "==> #{message}"
end
def error(message)
say("==> ! #{message}", :red)
exit 1
end
def success(message)
say("==> #{message}", :green)
end
def string_present?(maybe_string)
maybe_string.is_a?(String) && maybe_string.size > 0
end
def ensure_heroku_remote_exists_for(environment)
if remote_exists?(environment)
if Kumade.app_for(environment)
app_name = Kumade.app_for(environment)
if string_present?(app_name)
success("#{environment} is a Heroku remote")
else
error(%{Cannot deploy: "#{environment}" remote does not point to Heroku})
end
end
else
error(%{Cannot deploy: "#{environment}" remote does not exist})
end
end
def remote_exists?(remote_name)
`git remote`.split("\n").include?(remote_name)
end
end
end