forked from jsomers/lesswrong
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Rakefile
229 lines (195 loc) · 5.29 KB
/
Rakefile
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
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
require 'ftools'
require 'tempfile'
require 'pathname'
require 'shellwords'
namespace :test do
desc "Interactively run through the deployment test script."
task :manual do
# These are in here so they aren't required on the production server
$:.unshift 'tasks/manual_test_script/lib'
require 'active_support'
require 'manual_test_script'
ManualTestScript.run('test/manual.txt')
end
end
# Borrowed from capistrano
def sudo(command, options = {})
user = options[:as] && "-u #{options.delete(:as)}"
sudo_prompt_option = "-p 'sudo password: '"
sudo_command = ["sudo", sudo_prompt_option, user, command].compact.join(" ")
run sudo_command
end
def run(command)
puts "running `#{command}'"
unless system(command)
raise RuntimeError.new("Error running command: '#{command}'")
end
end
def basepath
Pathname(__FILE__).dirname.realpath
end
def shared_path
basepath.parent.parent + 'shared'
end
def r2_path
basepath + "r2"
end
def db_dump_path
path = basepath + "db" + "dumps"
path.mkpath unless path.exist?
path
end
def inifile
ENV['INI'] || (r2_path + "#{environment}.ini")
end
def user
ENV['APPLICATION_USER'] || raise("APPLICATION_USER environment variable must be set to run this task")
end
def application
ENV['APPLICATION'] || raise("APPLICATION environment variable variable must be set to run this task")
end
def environment
ENV['APPLICATION_ENV'] || raise("APPLICATION_ENV environment variable must be set to run this task")
end
def databases
@databases ||= begin
dbs = ENV['DATABASES'] || raise("DATABASES environment variable must be set to run this task")
dbs.split(/\s*,\s*/)
end
end
def app_server(action)
return unless [:start, :stop, :restart].include?(action)
sudo "#{action} paster"
end
# These tasks assume they are running in a capistrano managed directory structure.
namespace :app do
desc "Start the Application"
task :start do
app_server(:start)
end
desc "Stop the Application"
task :stop do
app_server(:stop)
end
desc "Restart the Application"
task :restart do
app_server(:restart)
end
end
namespace :deploy do
desc 'Run Reddit setup routine'
task :setup do
Dir.chdir r2_path
sudo "python setup.py install"
Dir.chdir basepath
sudo "chown -R #{user} #{r2_path}"
end
desc "Symlink the INI files into the release path"
task :symlink_ini do
Dir["/usr/local/etc/reddit/#{application}.*.ini"].each do |ini|
if File.basename(ini) =~ /#{Regexp.escape(application)}\.([^\.]+)\.ini/
target = "#{r2_path}/#{$1}.ini"
FileUtils.ln_sf(ini, target, :verbose => true)
end
end
end
desc 'Compress and concetenate JS and generate MD5 files'
task :process_static_files do
Dir.chdir r2_path
run "./compress_js.sh"
end
# For compatibilty
desc "Restart the Application"
task :restart do
Rake::Task['app:stop'].invoke
Rake::Task['app:start'].invoke
end
desc "Copy the lesswrong crontab to /etc/cron.d in production. Requires root permissions"
task :crontab do
crontab = basepath + 'config' + 'crontab'
target = "/etc/cron.d/lesswrong"
if environment == "production"
File.copy(crontab, target, true) # true = verbose
else
# Don't want the cron jobs running in non-production environments
File.unlink target rescue nil
end
end
end
desc "Hook for tasks that should run after code update"
task :after_update_code => %w[
deploy:symlink_ini
deploy:setup
deploy:process_static_files
deploy:crontab
]
# Set the databases variable in your local deploy configuration
# expects an array of PostgreSQL database names
# Example:
# set :databases, %w[reddit change query_queue]
namespace :postgresql do
def conf
@conf ||= begin
conf = {}
File.open(inifile.to_s) do |ini|
ini.each_line do |line|
next if line =~ /^\s*#/ # skip comments
next if line =~ /^\s*\[[^\]]+\]/ # skip sections
if line =~ /\s*([^\s=]+)\s*=\s*(.*)$/
conf[$1] = $2
end
end
end
conf
end
end
def db_conf(db, var)
key = [db, 'db', var].join('_')
conf[key]
end
# Common options
def postgresql_opts(database)
opts = []
opts << "--host=#{db_conf database, 'host'}"
opts << "--username=#{db_conf database, 'user'}"
opts << "--no-password" # Never prompt for password, its read from the file below
opts.join(" ")
end
def with_pgpass(db)
# Setup the pgpass file
pgpass = Tempfile.new("pgpass")
ENV['PGPASSFILE'] = pgpass.path
pgpass.puts [
db_conf(db, 'host'),
'*', # port
db_conf(db, 'name'),
db_conf(db, 'user'),
db_conf(db, 'pass')
].join(':')
pgpass.close
begin
yield
ensure
pgpass.unlink
end
end
def dump_file_path(db)
(db_dump_path + "#{db}.psql").to_s.shellescape
end
desc 'Dump the database'
task :dump do
databases.each do |db|
with_pgpass(db) do
run "pg_dump #{postgresql_opts(db)} -f #{dump_file_path(db)} -Fc #{db_conf(db, 'name')}"
end
end
end
desc 'Restore the latest database dump'
task :restore do
databases.each do |db|
with_pgpass(db) do
run "pg_restore #{postgresql_opts(db)} --no-owner --clean -d #{db_conf(db, 'name')} #{dump_file_path(db)} || true"
end
end
end
end