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?
DontDeployDebug is a Capistrano plugin that halts the deploy if finds debugging statement in your code.
It's only been tested with Capistrano 2. It requires the deploy server (e.g.
server to which the code is being deployed) to have UNIX-style find(1) and
grep(1) commands available in the deloy users path.
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.pryThe 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 => falseOr 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, falseFiles 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\//,
]Paths are relative from release_path and are prefixed with a / (slash).
Breakpoint patterns
By default, the gem will look for variations of:
require 'ruby-debug'; debugger
binding.pryThis 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 find and grep command
To first find the files, the gem executes a find of the release path to get
"coarse" list of files and then lets grep do the actual check. The command
used by default is:
find #{release_path} -name "*.rb" -exec grep -Hn 'debugger\|binding.pry' {} \;
A find with grep is used instead of a recursive grep for better
compatibility with non-GNU grep found some systems.
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
TODO
- Capistrano 3 compatibility
- Test with
capistrano-spec(https://github.com/technicalpickles/capistrano-spec)
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've used it on Redhat and Debian derived systems, 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.