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!

zendesk_remote_auth gem makes Zendesk SSO easy!

I extracted how we are doing Zendesk remote authentication from an app at Dealer Ignition, and stuck it in a small gem for your enjoyment. You can find it on GitHub.

Installation and Setup

Install:

gem install tobias-zendesk_remote_auth

Setup:

You will need to give the gem your token and authentication url, perhaps in an initializer:

Zendesk::RemoteAuth.token = 'YOUR-TOKEN'
Zendesk::RemoteAuth.auth_url = 'https://yourcompany.zendesk.com/access/remote/'

and config the gem in environment.rb (if using rails):

config.gem 'tobias-zendesk_remote_auth', :lib => 'zendesk_remote_auth', :source => http://gems.github.com'

Usage

Mixin the Zendesk::RemoteAuthHelper module wherever needed, then call:

zendesk_remote_auth_url(:name => 'user name',
                        :email => 'user email',
                        <optional params>)

This will return a url you can redirect the user to to log them in to your zendesk account.

As a convenience, you can pass a user object to zendesk_remote_auth_url:

zendesk_remote_auth_url(user)

This user must respond_to? :name and :email, and its :id will be used as the :external_id (making it useless with user objects that return an ephemeral object_id, but works well with ActiveRecord and the like). If the user object responds to :zendesk_organization, that will be used as the :o rganization for the call.

This method will generate and include the hash of the parameters for you if necessary.

Example Auth Controller

Here is an example controller that handles login and logout for zendesk:

# Uses restful-authentication style auth. 
# 
# Define the following in routes.rb:
# map.with_options :controller => 'zendesk_auth' do |zd|
#   zd.connect '/zendesk/authorize', :action => 'authorize'
#   zd.connect '/zendesk/logout', :action => 'logout'
# end
class ZendeskAuthController < ApplicationController
    include Zendesk::RemoteAuthHelper
     
    skip_before_filter :login_required, :only => :logout
     
    def authorize
        redirect_to zendesk_remote_auth_url(current_user)
    end
     
    def logout
        redirect_to logout_url
    end
     
    protected
    def login_required
        if !logged_in?
            flash[:notice] = 'You must log in to access the support site.'
            store_location
            redirect_to login_path
        end
    end
end

RAILS_ROOT/app Organization

As an app grows, so does the amount of files in app/models. Here is a simple tip to help reduce the clutter: move mailers, observers, and sweepers out of app/models into app/mailers, app/observers, and app/sweepers, respectively. For rails to still load them, you will need to modify config/environment.rb:

# clean up app/models a bit
%w{mailers observers sweepers}.each do |dir|
    config.load_paths << "#{RAILS_ROOT}/app/#{dir}"
end

As a bonus, you can now automatically record your observers with ActiveRecord instead of having to add them individually in environment.rb:

config.active_record.observers = Dir.glob("#{RAILS_ROOT}/app/observers/*.rb").collect do |filename|
    filename.split('/').last.split('.').first.to_sym
end
One issue with this reorganization is that the generators will continue to create mailers, observers, and sweepers in app/models. For me, that is not a big deal – I don’t create them often, and manually move them after generation. I suspect it would be trivial to adjust the generators to use the new path, but have not looked in to it.

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

script_finder gem

I recently published a ruby gem on github that simplifies running scripts from a script/ dir from anywhere in your project (rails or otherwise).

script_finder provides a script (called s@) in your path that searches in and up from the current dir for a folder (default: @script/) containing an executable file uniquely identified by the a prefix given as the first argument. It then calls that executable, passing the rest of the arguments to the called executable. If the given prefix is ambiguous, the script suggests unique prefixes.

Examples (in a rails app):

~/rails_app/app/views$ s c
--> calling '/Users/tobias/rails_app/script/console'
Loading development environment (Rails 2.1.0)
RowsLogger plugin enables mysql
>> exit
~/rails_app/app/views$ s r 'some ruby'
's r' was too ambiguous. Try:
's ru' for 'script/runner'
's re' for 'script/remote'
~/rails_app/app/views$ s ru 'some ruby'
--> calling '/Users/tobias/rails_app/script/runner some ruby'
...

The gem is not rails specific – out of the box it will work with any project that has a script/ directory. If you want to make your own version of the s@ script that looks for executables in a different dir (I would save this one as @c):

  #!/usr/bin/env ruby
 
require 'script_finder'
 
# looks for executables in a commands/ dir instead of script/.
ScriptFinder.find_and_execute(ARGV, 'commands')

Let me know if you have any problems/questions.