namespace :website do task(:default) { status } desc <<-DESC List of all your declared websites. DESC task :list do puts_title "Declared websites" list_displayer.display(Website.all) end desc <<-DESC Display the names of all the declared websites. As opposed to #{qcommand 'website:list'}, only the names are displayed, one name per line. This is useful for batch processing. DESC task :names do Website.all.each do |site| puts(site.name) end end desc <<-DESC Display the status of the current website. That is, whether it is declared or not, and if it is, displays its details. DESC task :status do site = fetch_current! puts_title "Website in the current directory" show(site, :include_status) end desc "Alias for task `status'." task(:show) { status } desc <<-DESC Declare the current website for subsequent deploys. This is necessary for the site to be made online. That is, for our routers to direct traffic to and from your VPS's. Environment variables: (optional) $SITEID: the name of the site for it to be referred to as later. Default: the name the current working directory. (optional) $TYPE: the ID or short name of the corresponding application type (#{qcommand "apptype:list"} to see what stock app. types are available, or #{qcommand "apptype:push"} to create your own). DESC task :declare do if site = fetch_current puts "Already declared (as #{q site})" next end # Find the application type type = if short = ENV["TYPE"] AppType.all.find { |t| t.short == short } or error! <<-MSG Application type #{q short} does not exist. For a list of available application types, run #{qcommand "apptype:list"}. MSG else autodetect_app_type end # Prepare site for declaration site = Website.new :name => name_of_current, :app_type => type # Attempt to push the declaration to the server try_save site do puts_title "Site declared" show(site) puts_subtitle("What to do next") puts_long <<-INFO 1) Database connection: ----------------------- If your site is database backed, and if you haven't done so already, you should now set up a database server with #{qcommand \ "db:server:setup"} and modify the production database connection settings accordingly in the configuration files (for example: wp-config.php for a WordPress blog, config/database.yml for a Rails application). 2) Backends: ------------ For your site to be online, webservers must receive requests from visitors and turn to backend processes (typically PHP or Rails) to process them. So there has to exist at least one webserver running, and at least one backend on one of the webserver VPS's. Such an architecture can be put in place by: * Setting up an initial, minimal stack, in an automated fashion: $ #{command "website:ensure_deployable"} * or going through each step manually for finer grained control. Example: $ #{command "webserver:setup ON=felix"} $ #{command "website:backends:add ON=felix"} The actions of whichever option you choose can be reverted or altered later. 3) Deployment: -------------- To upload the files of your website to the backends, you can either: * Download and run an automatically generated recipe, in the form of a Capfile: $ #{command "website:capfile:download"} $ cap deploy:setup deploy * Connect to each backend individually and upload the files to them. For example: $ #{command "website:backends:connect:details"} $ scp -P 1025 -r * foo@bar.flucti.net:~/mysite/current 5) Wait: -------- Wait a few moments for all automated actions to finish, and then your site should be online at http://#{site.domains.first}: $ #{command "progress"} 6) Domain: ---------- The default domain that has been attached automatically to your site can be replaced by attaching your actual domain with #{qcommand("website:domains:attach")} and removing the default one with #{qcommand("website:domains:detach")}. INFO end end desc <<-DESC Make sure the site can be deployed. For this to be the case, there has to exist at least one webserver: one is set up if none is yet. Also, the website has to be running on at least one of the VPS that run a webserver. Failing that, the VPS with the webserver last set up is chosen as the first host for the website. Those two parameters can be altered later. DESC task :ensure_deployable do website = fetch_current! if (count = website.backends.all.size).zero? webserver.ensure_any backends.add else puts_title "Backends present" puts "There exists #{count} backends." end end desc "Alias for task `website:backends:enter'." task(:enter) { backends.enter } desc <<-DESC Delete a website and all of its backends. This will take it offline and soft-clear all files stored in the backends (see #{qcommand 'website:backends:remove'}). DESC task :delete do site = fetch_current! confirm <<-WARN Deleting a website will make it will: * Cancel its declaration, making it unavailable. * Do the equivalent of #{qcommand "website:backends:remove"} for all the backends, so be sure to read the documentation of this command (#{qcommand '-e website:backends:remove'}) before confirming. WARN site.destroy puts_title "Request sent" puts "Website #{q site} scheduled for deletion." end def name_of_current ENV['SITEID'] || clean_name(Pathname.pwd.basename) end def fetch_current Website[name_of_current] end def fetch_current! fetch_current or error! <<-MSG The current website is undeclared yet (or at least not as #{q name_of_current}). Run #{qcommand "website:declare"} to declare it. MSG end def autodetect_app_type types = AppType.all.to_a static = types.find { |t| t.short == 'static' } (types - [static]). sort_by { |t| %w(rails php).index(t.short) || -1 }. each { |apptype| if test = apptype.detection filetype, path = test.split(' ', 2) return apptype if Kernel.test(filetype, path) end } static end def show(site, *args) list_displayer(*args).display_single_entry(site) end def list_displayer(include_status=false) Utilities::ListDisplayer.new(:title => :name) do |t| t.col("Status") { "Declared" } if include_status t.col("Name", :name) t.col("Type", :app_type) t.col("Domains") { |s| (domains = s.domains.to_a).any? ? domains * ', ' : '(none)' } end end end