DontDeployDebug
A gem against brain-farts.
How many times have you accidentally committed a debug statement and deployed it? To production? Ugh! I've been there, brothers and sisters! I've done it more times than I care to remember. So many that I finally decided to do something about it.
What?
It prevents code that has debug statements included from being deployed by Capistrano, along with a message about what was found and where to find it.
Example:
triggering after callbacks for `deploy:finalize_update'
* 2013-11-05 16:38:44 executing `deploy:find_ruby_breakpoints'
* executing "find /home/deploy/app/releases/20131105233842 -name \"*.rb\" -exec grep -Hn 'debugger\|binding.pry' {} \\;"
servers: ["server.example.org"]
[server.example.org] executing command
command finished in 621ms
*** Ruby debugger breakpoint found in deployed code. Deploy halted. ***
There was code found that contains debugging breakpoints:
/testfile.rb:3:require 'ruby-debug'; debugger
Please remove the code, commit the change and try your deploy again.
If you feel you have reached this message in error, please consult
https://github.com/xunker/dont_deploy_debug to learn how to exclude
certain files, or how to tune the detection parameters. To override
this check, set the 'IGNORE_RUBY_BREAKPOINTS' variable to true:
$ IGNORE_RUBY_BREAKPOINTS=true cap <environment> deploy
*** [deploy:update_code] rolling back
* executing "rm -rf /home/deploy/app/releases/20131105233842; true"
servers: ["server.example.org"]
[server.example.org] executing command
command finished in 159ms
Why?
Because even the rockstar-iest of ninjas sometimes forget to remove a 'debug'.
How?
It's a gem that hooks in to your Capistrano deploy process. After the code is updated on the server, but before it's made "live", the gem scans the release path for ruby source files that have "debug" statements in them. If any are found, the deploy is halted and rolled back, and a list of the offending files is displayed to the user.
By default, the gem looks for statements in *.rb
that are like:
require 'ruby-debug'; debugger
require 'ruby-debug'
debugger
debugger;
binding.pry
The gem will ignore test/*
, spec/*
, features/*
and config/deploy.rb
.
Ruby only?
Yes, for now. But if there is any interest it could be easily modified for any language where the source was parsable on the deployment server.
Installation
Add this line to your application's Gemfile:
# ":require => false" is important!
gem 'dont_deploy_debug', :require => false
Or from the command line if you aren't using bunder:
$ gem install dont_deploy_debug
Then, add the following to your Capistrano deploy.rb
:
require 'capistrano/dont_deploy_debug'
For basic usage, this is all that is required.
Configuration
Enable or disable the check
Be default, every deploy will be checked regardless of environment. This can be set programmatically by altering the 'skip_ruby_breakpoint_check' setting in your deloy.rb file:
# turn off for all
set :skip_ruby_breakpoint_check, true
# skip on stage
set :skip_ruby_breakpoint_check, (fetch(:rails_env) == 'stage')
# on for everyone (default)
set :skip_ruby_breakpoint_check, false
Files to exclude from check
By default, test/*
, spec/*
, features/*
and config/deploy.rb
are
ignored. You can modify this behaviour by changing the
'exclude_from_ruby_breakpoint_check' setting in your deploy.rb and adding or
removing regular expressions:
set :exclude_from_ruby_breakpoint_check, [
/^\.\/config\/deploy\.rb$/,
/^\.\/spec\//,
/^\.\/test\//,
/^\.\/features\//,
/^\.\/something_else_here\//,
]
Breakpoint patterns
By default, the gem will look for variations of:
require 'ruby-debug'; debugger
binding.pry
This can be changed by altering the "ruby_breakpoint_patterns" setting in your
deploy.rb
and adding or removing regular expressions:
set :ruby_breakpoint_patterns, [
/require [\'\"]ruby-debug[\'\"][;\n]\s*debugger/,
/^\s*debugger[;\n]/,
/^\s*debugger\s*$/,
/\bbinding\.pry\b/,
/some_other_debugger/
]
Server-side grep command
To first find the files, the gem executes a grep() of the release path to get "coarse" list of files and then lets ruby do the actual check. The command used by default is:
find #{release_path} -name "*.rb" -exec grep -Hn 'debugger\|binding.pry' {} \;
A find() and grep() is used instead of a recursive grep because I have no way of knowing if you are deploying to system with BSD, SYSV or GNU style tools.
You can change this command in your deploy.rb
with the
"ruby_breakpoint_grep_command" setting:
# default value is:
# Proc.new { "find #{release_path} -name \"*.rb\" -exec grep -Hn #{fetch(:ruby_breakpoint_trigger)} {} \\;" }
# pass it a Proc object so we can read release_path and other variables
# It MUST return a string
set :ruby_breakpoint_grep_command, Proc.new { "some better grep here" }
If you only want to change the pattern that grep() uses, you can set "ruby_breakpoint_trigger" instead:
# default value is " 'debugger\|binding.pry' "
# note the single quotes!
set :ruby_breakpoint_trigger, " 'some_other_pattern' "
Skipping check from command line
Finally, if you just want to deploy the damn'ed thing and skip the check temporarily, you can set the "IGNORE_RUBY_BREAKPOINTS" shell variable:
$ IGNORE_RUBY_BREAKPOINTS=true cap <environment> deploy
Caveats
This gem has not been throughly tested in any way. Like seriously. I use it, but I'm the only one so far. I know it works on Redhat linux and it will likely work in most linuxes. It should work on any BSD system, but YMMV.
If you find a case where it doesn't work please let me know.