source: trunk/locker/deploy/bin/rails @ 1426

Last change on this file since 1426 was 1426, checked in by mitchb, 14 years ago
Deploy enhancements to Ruby on Rails autoinstaller This pulls in changes which provide an easy knob for users to put their apps into production mode (which was available in earlier versions of RoR) and cause code changes to be picked up by the fcgi automatically without having to kill processes on all our servers (code contributed by Greg Brockman). (Merge of r1297:1411 from branches/locker-dev to trunk)
File size: 5.7 KB
Line 
1#!/usr/bin/perl
2use strict;
3use FindBin qw($Bin);
4use lib $Bin;
5use onserver;
6use Tie::File;
7
8setup();
9
10sub make_db {
11    my($type) = @_;
12    print "\nCreating $type SQL database for $sname...\n";
13    open GETPWD, '-|', "/mit/scripts/sql/bin$scriptsdev/get-password";
14    ($sqlhost, $sqluser, $sqlpass) = split(/\s/, <GETPWD>);
15    close GETPWD;
16    open SQLDB, '-|', "/mit/scripts/sql/bin$scriptsdev/get-next-database", "${addrlast}_${type}";
17    $sqldb = <SQLDB>;
18    close SQLDB;
19    open SQLDB, '-|', "/mit/scripts/sql/bin$scriptsdev/create-database", $sqldb;
20    $sqldb = <SQLDB>;
21    close SQLDB;
22    if($sqldb eq "") {
23        print "\nERROR:\n";
24        print "Your SQL account failed to create a SQL database.\n";
25        print "You should log in at http://sql.mit.edu to check whether\n";
26        print "your SQL account is at its database limit or its storage limit.\n";
27        print "If you cannot determine the cause of the problem, please\n";
28        print "feel free to contact sql\@mit.edu for assistance.\n";
29        open FAILED, ">.failed";
30        close FAILED;
31        exit 1;
32    }
33    return $sqldb;
34}
35
36my $dev_db = make_db("development");
37my $test_db = make_db("test");
38my $prod_db = make_db("production");
39
40system qw{rails -D -d mysql .};
41
42open PUBLIC_HTACCESS, ">public/.htaccess";
43print PUBLIC_HTACCESS <<EOF;
44# General Apache options
45Options +FollowSymLinks +ExecCGI
46
47# If you don't want Rails to look in certain directories,
48# use the following rewrite rules so that Apache won't rewrite certain requests
49#
50# Example:
51#   RewriteCond %{REQUEST_URI} ^/notrails.*
52#   RewriteRule .* - [L]
53
54# Redirect all requests not available on the filesystem to Rails
55# By default the cgi dispatcher is used which is very slow
56#
57# For better performance replace the dispatcher with the fastcgi one
58#
59# Example:
60#   RewriteRule ^(.*)\$ dispatch.fcgi [QSA,L]
61RewriteEngine On
62
63# If your Rails application is accessed via an Alias directive,
64# then you MUST also set the RewriteBase in this htaccess file.
65#
66# Example:
67#   Alias /myrailsapp /path/to/myrailsapp/public
68#   RewriteBase /myrailsapp
69
70RewriteRule ^\$ index.html [QSA]
71RewriteRule ^([^.]+)\$ \$1.html [QSA]
72RewriteCond %{REQUEST_FILENAME} !-f
73RewriteRule ^(.*)\$ dispatch.fcgi [QSA,L]
74
75# In case Rails experiences terminal errors
76# Instead of displaying this message you can supply a file here which will be rendered instead
77#
78# Example:
79#   ErrorDocument 500 /500.html
80
81RewriteBase /$addrend/public/
82EOF
83
84open HTACCESS, ">.htaccess";
85print HTACCESS <<EOF;
86RewriteEngine On
87RewriteRule ^(.*)\$ public/\$1 [QSA,L]
88RewriteBase /$addrend/
89EOF
90
91tie my @railsenv, 'Tie::File', 'config/environment.rb';
92unshift @railsenv, "# ENV['RAILS_ENV'] ||= 'production'";
93unshift @railsenv, "# Uncomment below to put Rails into production mode";
94unshift @railsenv, "";
95unshift @railsenv, "ENV['RAILS_RELATIVE_URL_ROOT'] = \"/$addrend\"";
96untie @railsenv;
97
98tie my @railsdb, 'Tie::File', 'config/database.yml';
99for (@railsdb) {
100    s/username:.*$/username: $sqluser/;
101    s/password:.*$/password: $sqlpass/;
102    s/host:.*$/host: $sqlhost/;
103    s/database:.*_development.*/database: $dev_db/;
104    s/database:.*_test.*/database: $test_db/;
105    s/database:.*_production.*/database: $prod_db/;
106}
107untie @railsdb;
108
109tie my @railswelcome, 'Tie::File', 'public/index.html';
110for (@railswelcome) {
111    s/Create your database/Sync your database/;
112    s/to create your database\..*/to create tables in your database.<\/p>/;
113}
114untie @railswelcome;
115
116tie my @railsfcgi, 'Tie::File', 'public/dispatch.fcgi';
117for (@railsfcgi) {
118    s/^[^#]*RailsFCGIHandler/## Commented out by scripts.mit.edu autoinstaller\n## RailsFCGIHandler/;
119}
120untie @railsfcgi;
121open RAILSFCGI, ">>public/dispatch.fcgi";
122print RAILSFCGI <<EOF;
123
124## Added by scripts.mit.edu autoinstaller to reload when app code changes
125Thread.abort_on_exception = true
126
127t1 = Thread.new do
128   RailsFCGIHandler.process!
129end
130
131t2 = Thread.new do
132   # List of directories to watch for changes before reload
133   Thread.current[:watched_dirs] = ['app', 'config', 'db', 'lib', 'public']
134   # Sample filter: /(\.rb|\.erb)\$/.  Default filter: watch all files
135   Thread.current[:watched_extensions] = //
136   # Iterations since last reload
137   Thread.current[:iterations] = 0
138
139   def modified(file)
140     begin
141       mtime = File.stat(file).mtime
142     rescue
143       false
144     else
145       if Thread.current[:iterations] == 0
146         Thread.current[:modifications][file] = mtime
147       end
148       Thread.current[:modifications][file] != mtime
149     end
150   end
151
152   # Don't symlink yourself into a loop.  Please.  Things will still work
153   # (Linux limits your symlink depth) but you will be sad
154   def modified_dir(dir)
155     Dir.new(dir).each do |file|
156       absfile = File.join(dir, file)
157       if FileTest.directory? absfile
158         next if file == '.' or file == '..'
159         return true if modified_dir(absfile)
160       else
161         return true if Thread.current[:watched_extensions] =~ absfile &&
162           modified(absfile)
163       end
164     end
165     false
166   end
167
168   def reload
169     Thread.current[:modifications] = {}
170     Thread.current[:iterations] = 0
171     RailsFCGIHandler.reload!
172   end
173
174   Thread.current[:modifications] = {}
175   # Wait until the modify time changes, then reload.
176   while true
177     reload if Thread.current[:watched_dirs].inject(false) {|z, dir| z || modified_dir(File.join(File.dirname(__FILE__), '..', dir))}
178     Thread.current[:iterations] += 1
179     sleep 1
180   end
181end
182
183t1.join
184t2.join
185## End of scripts.mit.edu autoinstaller additions
186EOF
187
188print "Your application is located in:\n";
189print "  /mit/$USER/web_scripts/$addrend/\n";
190print "To run programs like rake or script/generate, run\n";
191print "  'ssh -k $USER\@scripts' and cd to the above directory.\n\n";
192press_enter;
193
194exit 0;
Note: See TracBrowser for help on using the repository browser.