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

Last change on this file since 2370 was 2287, checked in by glasgall, 12 years ago
Merge in 2259:2281 (fix Rails 3 on scripts, for good this time)
  • Property svn:executable set to *
File size: 8.0 KB
Line 
1#!/usr/bin/perl
2use strict;
3use FindBin qw($Bin);
4use lib $Bin;
5use onserver;
6use Tie::File;
7use Cwd;
8
9setup();
10
11sub make_db {
12    my($type) = @_;
13    print "\nCreating $type SQL database for $sname...\n";
14    open GETPWD, '-|', "/mit/scripts/sql/bin$scriptsdev/get-password";
15    ($sqlhost, $sqluser, $sqlpass) = split(/\s/, <GETPWD>);
16    close GETPWD;
17    open SQLDB, '-|', "/mit/scripts/sql/bin$scriptsdev/get-next-database", "${addrlast}_${type}";
18    $sqldb = <SQLDB>;
19    close SQLDB;
20    open SQLDB, '-|', "/mit/scripts/sql/bin$scriptsdev/create-database", $sqldb;
21    $sqldb = <SQLDB>;
22    close SQLDB;
23    if($sqldb eq "") {
24        print "\nERROR:\n";
25        print "Your SQL account failed to create a SQL database.\n";
26        print "You should log in at http://sql.mit.edu to check whether\n";
27        print "your SQL account is at its database limit or its storage limit.\n";
28        print "If you cannot determine the cause of the problem, please\n";
29        print "feel free to contact sql\@mit.edu for assistance.\n";
30        exit 1;
31    }
32    return $sqldb;
33}
34
35my $dev_db = make_db("development");
36my $test_db = make_db("test");
37my $prod_db = make_db("production");
38
39my $cwd = getcwd;
40system("rails", "new", $cwd ,"-d", "mysql");
41my $appdir = `basename $cwd`;
42chomp $appdir;
43
44open APPLICATION_RB, "config/application.rb";
45my $appclass;
46while(<APPLICATION_RB>) {
47    if (/module (\w+)\n/) {
48        $appclass = $1;
49        last;
50    }
51}
52close APPLICATION_RB;
53if (!$appclass) {
54    die "Couldn't find application class name - plase email scripts\@mit.edu with the names of your locker and the application you tried to create. Sorry!";
55}
56
57open PUBLIC_HTACCESS, ">public/.htaccess";
58print PUBLIC_HTACCESS <<EOF;
59# General Apache options
60Options +FollowSymLinks +ExecCGI
61
62# If you don't want Rails to look in certain directories,
63# use the following rewrite rules so that Apache won't rewrite certain requests
64#
65# Example:
66#   RewriteCond %{REQUEST_URI} ^/notrails.*
67#   RewriteRule .* - [L]
68
69# Redirect all requests not available on the filesystem to Rails
70# By default the cgi dispatcher is used which is very slow
71#
72# For better performance replace the dispatcher with the fastcgi one
73#
74# Example:
75#   RewriteRule ^(.*)\$ dispatch.fcgi [QSA,L]
76RewriteEngine On
77
78# If your Rails application is accessed via an Alias directive,
79# then you MUST also set the RewriteBase in this htaccess file.
80#
81# Example:
82#   Alias /myrailsapp /path/to/myrailsapp/public
83#   RewriteBase /myrailsapp
84
85RewriteCond index.html -f
86RewriteRule ^\$ index.html [QSA]
87RewriteCond %{REQUEST_FILENAME} !-f
88RewriteRule ^(.*)\$ dispatch.fcgi/\$1 [QSA,L]
89
90# In case Rails experiences terminal errors
91# Instead of displaying this message you can supply a file here which will be rendered instead
92#
93# Example:
94#   ErrorDocument 500 /500.html
95
96EOF
97
98open HTACCESS, ">.htaccess";
99print HTACCESS <<EOF;
100RewriteEngine On
101RewriteRule ^(.*)\$ public/\$1 [QSA,L]
102
103EOF
104
105tie my @railsenv, 'Tie::File', 'config/environment.rb';
106unshift @railsenv, "# ENV['RAILS_ENV'] ||= 'production'";
107unshift @railsenv, "# Uncomment below to put Rails into production mode";
108unshift @railsenv, "";
109untie @railsenv;
110
111tie my @railsdb, 'Tie::File', 'config/database.yml';
112for (@railsdb) {
113    s/username:.*$/username: $sqluser/;
114    s/password:.*$/password: $sqlpass/;
115    s/host:.*$/host: $sqlhost/;
116    s/database:.*_development.*/database: $dev_db/;
117    s/database:.*_test.*/database: $test_db/;
118    s/database:.*_production.*/database: $prod_db/;
119}
120untie @railsdb;
121
122tie my @railswelcome, 'Tie::File', 'public/index.html';
123for (@railswelcome) {
124    s/Create your database/Sync your database/;
125    s/to create your database\..*/to create tables in your database.<\/p>/;
126}
127untie @railswelcome;
128
129# set config.action_controller.asset_host for all environments,
130# so urls to static assets are generated correctly
131# regardless of how the app is accessed
132my $rails_assethost = "  config.action_controller.asset_host = \"//$USER.scripts.mit.edu/$appdir/public\"";
133my @environments = ('development', 'production', 'test');
134
135for my $environment (@environments) {
136    tie my @envfile, 'Tie::File', "config/environments/$environment.rb";
137    my $i = 0;
138    for (@envfile) {
139        if (/^end$/) {
140            last;
141        }
142        ++$i;
143    }
144    splice @envfile, $i, 1, ($rails_assethost, 'end');
145    untie @envfile;
146}
147
148
149tie my @railsfcgi, 'Tie::File', 'public/dispatch.fcgi';
150for (@railsfcgi) {
151    s/^[^#]*RailsFCGIHandler/## Commented out by scripts.mit.edu autoinstaller\n## RailsFCGIHandler/;
152}
153untie @railsfcgi;
154open RAILSFCGI, ">>public/dispatch.fcgi";
155print RAILSFCGI "#!/usr/bin/ruby\n";
156print RAILSFCGI <<EOF;
157require File.join(File.dirname(__FILE__), '../config/environment')       
158require 'rack'
159
160## Added by scripts.mit.edu autoinstaller to reload when app code changes
161Thread.abort_on_exception = true
162
163# Strip public/dispatch.fcgi out of SCRIPT_NAME so Rails generates nicer URLs
164class ScriptNameRewriter
165 
166  def initialize(app)
167    \@app = app
168  end
169
170  def call(env)
171    if env['SCRIPT_NAME'] =~ /dispatch\.fcgi/
172      env['SCRIPT_NAME'].gsub!(/public\\/dispatch\.fcgi/,'')
173    end
174    \@app.call(env)
175  end
176end
177
178
179t1 = Thread.new do
180  dispatch_logger = Logger.new(File.join(Rails.root,'log/dispatcher.log'))
181
182  begin
183    Rack::Handler::FastCGI.run ScriptNameRewriter.new(Rack::URLMap.new("/" => ${appclass}::Application))
184  rescue => e
185   dispatch_logger.error(e)
186   raise e
187  end
188end
189t2 = Thread.new do
190   # List of directories to watch for changes before reload.
191   # You may want to also watch public or vendor, depending on your needs.
192   Thread.current[:watched_dirs] = ['app', 'config', 'db', 'lib']
193
194   # List of specific files to watch for changes.
195   Thread.current[:watched_files] = ['public/dispatch.fcgi',
196                                     'public/.htaccess']
197   # Sample filter: /(\.rb|\.erb)\$/.  Default filter: watch all files
198   Thread.current[:watched_extensions] = //
199   # Iterations since last reload
200   Thread.current[:iterations] = 0
201
202   def modified(file)
203     begin
204       mtime = File.stat(file).mtime
205     rescue
206       false
207     else
208       if Thread.current[:iterations] == 0
209         Thread.current[:modifications][file] = mtime
210       end
211       Thread.current[:modifications][file] != mtime
212     end
213   end
214
215   # Don't symlink yourself into a loop.  Please.  Things will still work
216   # (Linux limits your symlink depth) but you will be sad
217   def modified_dir(dir)
218     Dir.new(dir).each do |file|
219       absfile = File.join(dir, file)
220       if FileTest.directory? absfile
221         next if file == '.' or file == '..'
222         return true if modified_dir(absfile)
223       else
224         return true if Thread.current[:watched_extensions] =~ absfile &&
225           modified(absfile)
226       end
227     end
228     false
229   end
230
231   def reload
232     Thread.current[:modifications] = {}
233     Thread.current[:iterations] = 0
234     # This is a kludge, but at the same time it works.
235     # Will kill the current FCGI process so that it is reloaded
236     # at next request.
237     raise RuntimeError
238   end
239
240   Thread.current[:modifications] = {}
241   # Wait until the modify time changes, then reload.
242   while true
243     dir_modified = Thread.current[:watched_dirs].inject(false) {|z, dir| z || modified_dir(File.join(File.dirname(__FILE__), '..', dir))}
244     file_modified = Thread.current[:watched_files].inject(false) {|z, file| z || modified(File.join(File.dirname(__FILE__), '..', file))}
245     reload if dir_modified || file_modified
246     Thread.current[:iterations] += 1
247     sleep 1
248   end
249end
250
251t1.join
252t2.join
253## End of scripts.mit.edu autoinstaller additions
254EOF
255chmod 0755,'public/dispatch.fcgi';
256
257# static-cat doesn't whitelist .txt files
258chmod 0777, 'public/robots.txt'; 
259
260# have to explicitly take a dependency on fcgi
261# ruby1.9 means we need to take a dependency on minitest
262# for rails console to work
263open GEMFILE, ">>Gemfile";
264print GEMFILE "gem 'fcgi'\n";
265print GEMFILE "gem 'minitest'\n";
266close GEMFILE;
267
268print "Your application is located in:\n";
269print "  /mit/$USER/web_scripts/$addrend/\n";
270print "To run programs like rake or rails generate, run\n";
271print "  'ssh -k $USER\@scripts' and cd to the above directory.\n\n";
272press_enter;
273
274exit 0;
Note: See TracBrowser for help on using the repository browser.