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

Last change on this file since 2764 was 2606, checked in by glasgall, 10 years ago
Fix autoinstaller for whatever newer version of Ruby changed either File.dirname or require behavior
  • 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.expand_path(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.