Notify a Campfire room on cap deploy

We use Campfire for internal communication, and I’ve lately been pushing notifications there for all to see (Zendesk ticket updates, git repo pushes, etc). We decided it would be useful for the support team to know when a deployment occurs. I googled a bit to see if anyone had shared a Capistrano recipe, and did not find one. So I’m sharing mine.

Using the tinder gem, its super easy:

Enjoy!

server_remote gem

I just re-released my server_remote plugin as a gem server_remote on github. I converted it to a gem to make it easier to use in multiple apps, and to make it easier to update (see here for the blog entry on the (now obselete) plugin).

It is a gem that provides support for running commands on remote server. Once set up, it provides commands via script/remote:

  • remote shell – same as ssh’ing to the server (this is the default command, so it can be called with just remote)
  • remote console – executes a script/console on the server
  • remote logtail – executes tail -f log/<environment>.log on the server
  • remote cmd <some command> executes command on the server, displaying the result. It cd‘s to the remote app root first.
  • remote scp <local_file> :<remote_file> provides scp. Prefix remote files with ‘:’
Configuration is in config/server_remote.yml, and is grouped into profiles.

Here is the output of remote usage:

Executes commands on a remote server over ssh. Configuration is in:
/Users/tobias/customers/DealerIgnition/dealer_ignition/script/../config/server_remote.yml
 
You can override the profile used with -p profile. The default profile is: app
 
Learn more in the readme:
/opt/local/lib/ruby/gems/1.8/gems/tobias-server_remote-0.2.0/lib/server_remote/../../README.textile
 
remote commands are:
 
DEFAULT COMMAND   shell
 
cmd               executes an arbitrary command on the server after a cd to the app path
commands          List all 'remote' commands
console           executes remote console
help              Provide help documentation for a command
logtail           executes remote tail -f on the log
scp               copies files over scp (prefix remote files with ':')
shell             executes remote shell
usage             prints usage message
 
For help on a particular command, use 'remote help COMMAND'.

It uses remi’s simplecli gem.

I plan to add other commands as needed, or you can open up Remote::Commands and add your own.

Installation

You will need to install the gem (only once), then setup any apps where you want to use it.

sudo gem install tobias-server_remote --source http://gems.github.com/
server_remotify path_to_app

server_remote - A Rails plugin for easily accessing servers

Note: this post is out of date. This tool is now a gem instead of a plugin; read all about it here.

I just released server_remote on github. It is a plugin for connecting to remote servers. Once installed, it provides commands via script/remote:

* remote shell – same as ssh’ing to the server (this is the default command, so it can be called with just remote)

* remote console – executes a script/console on the server

* remote logtail – executes tail -f log/<environment>.log on the server

Configuration is in config/server_remote.yml, and is grouped into profiles.

Here is the output of remote usage:

 Executes commands on a remote server over ssh. Configuration is in:
/Users/tobias/customers/DropZite/restaurantZite/config/server_remote.yml
 
You can override the profile used with -p profile. The default profile is: app
 
Learn more in the readme:
/Users/tobias/customers/DropZite/restaurantZite/vendor/plugins/server_remote/lib/README.textile
 
remote commands are:
 
DEFAULT COMMAND   shell
 
commands          List all 'remote' commands
console           executes remote console
help              Provide help documentation for a command
logtail           executes remote tail -f on the log
shell             executes remote shell
usage             prints usage message
 
For help on a particular command, use 'remote help COMMAND'.

It uses remi’s simplecli gem.





I plan to add other commands as needed, or you can open up Remote::Commands and add your own. Install with: script/plugin install git://github.com/tobias/server_remote.git

Stepping off the Rails - adventures with Sinatra (Part 2)

In this episode, our trusty adventurer actually runs his Sinatra app, and deploys it to Passenger on shared hosting. See Part 1 for details of building the application.

Launching locally: two ways to skin a cat

I realized that in Part 1 I did not cover launching the app to hit it from the browser. It’s easy! To launch the app, use ruby app_name.rb. This will fire up a mongrel instance on port 4567 for your viewing pleasure.

Once you have defined your rack configuration (see below), you can also run the app inside rack locally with rackup config.ru to test your rack settings. This will launch rack inside mongrel on port 9292. Thanks to @jnunemaker for the tip. In fact, John’s article is what I used as a basis for my deployment, with a few changes to support file based view templates.

Rack Configuration

To configure the application to run on rack under Passenger, you need to define a rack configuration file. Passenger expects that file to be named config.ru (see Deploying a Rack-based Ruby application in the Passenger documentation). Here is a minimum config.ru to run the application:

require 'rubygems'
require 'sinatra'
 
disable :run
 
require 'urlunwind.rb'
run Sinatra.application

The only real configuration there is disable :run. This prevents Sinatra from starting a mongrel on port 4567 when the app file is required. This configuration would work for an app that uses no file based templates, and does not reference anything in public/. If you run this config with rackup on url_unwind (rackup config.ru), you’ll see errors like:

Errno::ENOENT: No such file or directory - /opt/local/bin/views/index.haml









This is because rack by default sets its base directory to be the path to the called executable (and on my machine, rackup lives in /opt/local/bin/). So we’ll need to explicitly set the paths:

require 'rubygems'
require 'sinatra'
 
disable :run
set :views, File.dirname(__FILE__) + '/views'
set :public, File.dirname(__FILE__) + '/public'
set :app_file, __FILE__
 
require 'urlunwind.rb'
run Sinatra.application

Now the app should run properly with rackup.

Logging

Sinatra uses rack’s built in logging to log requests, and these log messages get printed to standard out. It would be nice to log these to a file, and we can do that as well in config.ru (based on this tip from Chris Schneider). We’ll also need to turn error raising back on, since by default Sinatra swallows errors in production mode:

require 'rubygems'
require 'sinatra'
 
disable :run
set :env, :production
set :raise_errors, true
set :views, File.dirname(__FILE__) + '/views'
set :public, File.dirname(__FILE__) + '/public'
set :app_file, __FILE__
 
log = File.new("log/sinatra.log", "a")
STDOUT.reopen(log)
STDERR.reopen(log)
 
require 'urlunwind.rb'
run Sinatra.application

This allows you to add your own logging messages as well, just puts, print, or p@ whatever you want to log. *Note:* you will need to create the @log/ directory for this to work.

Deploy with Capistrano

I used Capistrano to deploy to Dreamhost, and based my Capfile of off John’s directions here. I modified it a bit to pull from github, and to create the tmp/ and log/ directories if they do not exist. Here is my Capfile:

#-*-ruby-*-
load 'deploy' if respond_to?(:namespace) # cap2 differentiator
 
default_run_options[:pty] = true
 
# be sure to change these
set :user, 'app_user'
set :domain, 'urlunwind.com'
set :application, 'url_unwind'
set :git_path_prefix, "git@github.com/tobias/"
 
# the rest should be good
set :repository, "#{git_path_prefix}#{application}.git"
set :deploy_to, "/home/#{user}/#{domain}"
set :deploy_via, :remote_cache
set :scm, 'git'
set :branch, 'master'
#set :git_shallow_clone, 1
set :scm_verbose, true
set :use_sudo, false
 
server domain, :app, :web
 
namespace :deploy do
task :restart do
run "test -d #{current_path}/tmp || mkdir #{current_path}/tmp"
run "test -d #{current_path}/log || mkdir #{current_path}/log"
run "touch #{current_path}/tmp/restart.txt"
end
end

Since the Sinatra gem is not installed on Dreamhost, I put it in vendor/ within the app. Since it is not a gem, it must be required with the full path to the base .rb file, both in config.ru and in the app file itself (urlunwind.rb in this case). Here is the final config.ru:

require 'rubygems'
require 'vendor/sinatra/lib/sinatra.rb'
 
disable :run
set :env, :production
set :raise_errors, true
set :views, File.dirname(__FILE__) + '/views'
set :public, File.dirname(__FILE__) + '/public'
set :app_file, __FILE__
 
log = File.new("log/sinatra.log", "a")
STDOUT.reopen(log)
STDERR.reopen(log)
 
require 'urlunwind.rb'
run Sinatra.application