capistrano-ext-projectdx 0.1.14 → 0.1.20
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/deploy.sh +7 -1
- data/lib/capistrano-ext-projectdx.rb +0 -1
- data/lib/capistrano/ext/projectdx/cache.rb +24 -2
- data/lib/capistrano/ext/projectdx/docs.rb +2 -2
- data/lib/capistrano/ext/projectdx/misc.rb +1 -1
- data/lib/capistrano/ext/projectdx/projectdx.rb +1 -9
- metadata +8 -12
- data/lib/database_operations.rb +0 -68
- data/lib/projectdx/tasks.rb +0 -87
- data/lib/rf_filtering.rb +0 -64
- data/lib/sql_obfuscator.rb +0 -74
data/bin/deploy.sh
CHANGED
@@ -18,6 +18,12 @@ if [ -z "${DEPLOY_VERSION}" ]; then
|
|
18
18
|
export DEPLOY_VERSION=`git tag -l "${STAGE}/*" | egrep "^${STAGE}/[0-9]{4}-[0-9][0-9]-[0-9][0-9](\.[0-9]+)?" | sort -r | head -1`
|
19
19
|
fi
|
20
20
|
|
21
|
+
if [ "${APP}" == "projectdx-pdxrails" ]; then
|
22
|
+
DEPLOY=deploy:full
|
23
|
+
else
|
24
|
+
DEPLOY=deploy
|
25
|
+
fi
|
26
|
+
|
21
27
|
if [ -z "${DEPLOY_VERSION}" ]; then
|
22
28
|
echo "No deployable version found!"
|
23
29
|
EXIT=1
|
@@ -31,7 +37,7 @@ else
|
|
31
37
|
. .agent
|
32
38
|
ssh-add
|
33
39
|
|
34
|
-
bundle exec cap ${STAGE}
|
40
|
+
bundle exec cap "${STAGE}" "${DEPLOY}"
|
35
41
|
EXIT=$?
|
36
42
|
|
37
43
|
ssh-agent -k
|
@@ -1 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/database_operations'
|
@@ -1,8 +1,30 @@
|
|
1
1
|
namespace :cache do
|
2
|
-
desc "
|
2
|
+
desc "Create cachedirs"
|
3
|
+
task :setup, :roles => :web do
|
4
|
+
# note: source is relative to #{current_path}
|
5
|
+
def setup_cache_path(name, source)
|
6
|
+
cache_path=fetch(:cache_path, "/dev/shm/apps/#{application}")
|
7
|
+
local_cache_path="#{current_path}/#{source}"
|
8
|
+
shm_cache_patch="#{cache_path}/#{name}"
|
9
|
+
run %Q{ mkdir -p "#{shm_cache_patch}" }
|
10
|
+
run %Q{ if [ -d #{local_cache_path} ]; then rsync -qa #{local_cache_path}/ #{shm_cache_patch} && rm -rf #{local_cache_path}; fi }
|
11
|
+
run %Q{ ln -s #{shm_cache_patch}/ #{local_cache_path} }
|
12
|
+
end
|
13
|
+
setup_cache_path('fragment_cache', 'tmp/fragment_cache')
|
14
|
+
setup_cache_path('public_cache', 'public/cache')
|
15
|
+
fetch(:caches, {}).each do |k,v|
|
16
|
+
setup_cache_path(k, v)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
after "deploy:symlink", "cache:setup"
|
21
|
+
|
22
|
+
|
23
|
+
desc "Empty out shared cachedir, fragment cache, and the cached javascript and css"
|
3
24
|
task :clean, :roles => :web do
|
4
25
|
run "shopt -s nullglob; cd #{current_path} && for i in ./public/javascripts/cache_*.js; do /bin/rm ${i}; done"
|
5
26
|
run "shopt -s nullglob; cd #{current_path} && for i in ./public/stylesheets/cache_*.css; do /bin/rm ${i}; done"
|
6
|
-
run "shopt -s nullglob; cd #{
|
27
|
+
run "shopt -s nullglob; cd #{current_path} && /bin/rm -rf ./public/cache/*"
|
28
|
+
run "shopt -s nullglob; cd #{current_path} && /bin/rm -rf ./tmp/fragment_cache/*"
|
7
29
|
end
|
8
30
|
end
|
@@ -3,7 +3,7 @@ Capistrano::Configuration.instance.load do
|
|
3
3
|
namespace :docs do
|
4
4
|
desc "update docs directory"
|
5
5
|
task :default do
|
6
|
-
run "cd #{current_path} && rake doc:local RDOC_DIR=#{docsdir}"
|
6
|
+
run "cd #{current_path} && bundle exec rake doc:local RDOC_DIR=#{docsdir}"
|
7
7
|
end
|
8
8
|
desc "force rebuild of docs directory"
|
9
9
|
task :rebuild do
|
@@ -12,4 +12,4 @@ Capistrano::Configuration.instance.load do
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
15
|
-
end
|
15
|
+
end
|
@@ -15,14 +15,6 @@ Capistrano::Configuration.instance.load do
|
|
15
15
|
end
|
16
16
|
|
17
17
|
namespace :deploy do
|
18
|
-
desc "install database.yml, and other things "
|
19
|
-
task :local_config do
|
20
|
-
run "mkdir -p #{shared_path}/cache"
|
21
|
-
run "/bin/ln -nsf #{release_path}/../../shared/cache #{release_path}/public/cache"
|
22
|
-
end
|
23
|
-
|
24
|
-
after "deploy:symlink", "deploy:local_config"
|
25
|
-
|
26
18
|
desc "update selinux context"
|
27
19
|
task :selinux do
|
28
20
|
run %Q{if [ -d #{release_path} ]; then
|
@@ -73,7 +65,7 @@ Capistrano::Configuration.instance.load do
|
|
73
65
|
if releases.length < 2
|
74
66
|
abort "could not rollback the code because there is no prior release"
|
75
67
|
else
|
76
|
-
rake = fetch(:rake, "rake")
|
68
|
+
rake = fetch(:rake, "bundle exec rake")
|
77
69
|
rails_env = fetch(:rails_env, "production")
|
78
70
|
migrate_env = fetch(:migrate_env, "")
|
79
71
|
migrate_target = fetch(:migrate_target, :latest)
|
metadata
CHANGED
@@ -1,25 +1,25 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: capistrano-ext-projectdx
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 51
|
5
|
+
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 20
|
10
|
+
version: 0.1.20
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Darrell Fuhriman
|
14
14
|
- Joel Hoffman
|
15
15
|
- Sam Livingston-Gray
|
16
16
|
- Laurie Kemmerer
|
17
|
+
- Dave Miller
|
17
18
|
autorequire:
|
18
19
|
bindir: bin
|
19
20
|
cert_chain: []
|
20
21
|
|
21
|
-
date:
|
22
|
-
default_executable:
|
22
|
+
date: 2012-06-25 00:00:00 Z
|
23
23
|
dependencies: []
|
24
24
|
|
25
25
|
description: Local extensions to capistrano, which others may find useful
|
@@ -28,6 +28,7 @@ email:
|
|
28
28
|
- joel@renewfund.com
|
29
29
|
- sam@renewfund.com
|
30
30
|
- laurie@renewfund.com
|
31
|
+
- dave.miller@renewfund.com
|
31
32
|
executables: []
|
32
33
|
|
33
34
|
extensions: []
|
@@ -47,11 +48,6 @@ files:
|
|
47
48
|
- lib/capistrano/ext/projectdx/web.rb
|
48
49
|
- lib/capistrano/ext/projectdx.rb
|
49
50
|
- lib/capistrano-ext-projectdx.rb
|
50
|
-
- lib/database_operations.rb
|
51
|
-
- lib/projectdx/tasks.rb
|
52
|
-
- lib/rf_filtering.rb
|
53
|
-
- lib/sql_obfuscator.rb
|
54
|
-
has_rdoc: true
|
55
51
|
homepage: http://github.com/projectdx/capistrano-ext-projectdx
|
56
52
|
licenses: []
|
57
53
|
|
@@ -83,7 +79,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
83
79
|
requirements: []
|
84
80
|
|
85
81
|
rubyforge_project: capistrano-ext-projectdx
|
86
|
-
rubygems_version: 1.
|
82
|
+
rubygems_version: 1.8.24
|
87
83
|
signing_key:
|
88
84
|
specification_version: 3
|
89
85
|
summary: Local extensions to capistrano, which others may find useful
|
data/lib/database_operations.rb
DELETED
@@ -1,68 +0,0 @@
|
|
1
|
-
require 'open3'
|
2
|
-
require 'tempfile'
|
3
|
-
class DatabaseOperations
|
4
|
-
def self.pg(cfg, cmd)
|
5
|
-
ENV['PGPASSWORD'] = cfg["password"]
|
6
|
-
|
7
|
-
args = []
|
8
|
-
args << %{-h "#{cfg["host"]}"} if cfg["host"]
|
9
|
-
args << %{-U "#{cfg["username"]}"} if cfg["username"]
|
10
|
-
args << %{-p "#{cfg["port"]}"} if cfg["port"]
|
11
|
-
args << %{-w}
|
12
|
-
|
13
|
-
%x{#{cmd} #{args.join(' ')} "#{cfg['database']}"}
|
14
|
-
ensure
|
15
|
-
ENV.delete('PGPASSWORD')
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.load_database_schema!(cfg, file)
|
19
|
-
pg(cfg, 'createdb') unless pg(cfg, "psql -l") =~ /^ #{cfg['database']}\s*\|/m
|
20
|
-
|
21
|
-
Tempfile.open('initdb') do |f|
|
22
|
-
f.puts "set client_min_messages=error;"
|
23
|
-
f.puts "drop schema if exists public cascade;"
|
24
|
-
f.puts "create schema public;"
|
25
|
-
f.puts "drop schema if exists tiger cascade;"
|
26
|
-
|
27
|
-
f.puts "drop language if exists plpgsql cascade;"
|
28
|
-
f.puts "create language plpgsql;"
|
29
|
-
f.flush
|
30
|
-
pg(cfg, "psql -f #{f.path}")
|
31
|
-
end
|
32
|
-
|
33
|
-
pg cfg, %{psql -f "#{file}"}
|
34
|
-
end
|
35
|
-
|
36
|
-
def self.dump_database_schema!(cfg, file)
|
37
|
-
search_path = cfg["schema_search_path"]
|
38
|
-
search_path = search_path.split(',').map{|x| "--schema=#{x}"}.join(' ') if search_path
|
39
|
-
|
40
|
-
File.open(Rails.root.join(file), "w") { |f|
|
41
|
-
f.puts "begin;"
|
42
|
-
f.write pg(cfg, %{pg_dump -n tiger}).gsub('CREATE FUNCTION', 'CREATE OR REPLACE FUNCTION').lines.reject { |l| l =~ /soundex/ } * ""
|
43
|
-
f.write pg(cfg, %{pg_dump -s -n public}).gsub('CREATE FUNCTION', 'CREATE OR REPLACE FUNCTION')
|
44
|
-
f.write pg(cfg, %{pg_dump -a -t spatial_ref_sys})
|
45
|
-
f.write pg(cfg, %{pg_dump -a -t schema_migrations})
|
46
|
-
f.puts "commit;"
|
47
|
-
}
|
48
|
-
end
|
49
|
-
|
50
|
-
def self.load_views_and_triggers!
|
51
|
-
cfg = ActiveRecord::Base.configurations[Rails.env]
|
52
|
-
unless pg(cfg, "createlang -l") =~ /plpgsql/
|
53
|
-
pg(cfg, "createlang plpgsql")
|
54
|
-
end
|
55
|
-
|
56
|
-
output = nil
|
57
|
-
|
58
|
-
Tempfile.open('load_views') do |temp|
|
59
|
-
|
60
|
-
Dir.glob(Rails.root.join('lib', 'sql_erb', '[0-9]*.sql.erb')).sort_by { |f| ('0.%s' % File.split(f).last.gsub(/\D.*/,'')).to_f }.each do |fpath|
|
61
|
-
temp.puts File.open(fpath){|io| ERB.new(io.read).result }
|
62
|
-
end
|
63
|
-
temp.flush
|
64
|
-
output = pg cfg, %{psql --single-transaction -f #{temp.path} }
|
65
|
-
end
|
66
|
-
output
|
67
|
-
end
|
68
|
-
end
|
data/lib/projectdx/tasks.rb
DELETED
@@ -1,87 +0,0 @@
|
|
1
|
-
def copy(src,dst)
|
2
|
-
%x{if [ -e #{dst} ]; then mv #{dst} #{dst}.bak; fi; cp #{src} #{dst}}
|
3
|
-
end
|
4
|
-
|
5
|
-
require File.dirname(__FILE__) + '/../database_operations'
|
6
|
-
|
7
|
-
namespace :ci do
|
8
|
-
task :setup => 'setup:default'
|
9
|
-
|
10
|
-
namespace :setup do
|
11
|
-
task :default => [:copy_config, :clone_structure]
|
12
|
-
|
13
|
-
task :cucumber => [:copy_config, :clean_logdir, :clean_cache, :default]
|
14
|
-
|
15
|
-
task :clone_structure do
|
16
|
-
abcs = YAML.load_file('config/database.yml')
|
17
|
-
DatabaseOperations.dump_database_schema!(abcs['reference'], 'db/ci_structure.sql')
|
18
|
-
DatabaseOperations.load_database_schema!(abcs['test'], 'db/ci_structure.sql')
|
19
|
-
puts %x{env RAILS_ENV=test rake db:migrate}
|
20
|
-
DatabaseOperations.dump_database_schema!(abcs['test'], 'db/ci_structure.sql')
|
21
|
-
end
|
22
|
-
|
23
|
-
task :copy_config do
|
24
|
-
ci = YAML.load_file('config/database.ci.yml')
|
25
|
-
ci['login']['database'] = '%s-ci-%s' % [ci['login']['application'], %x{hostname}.strip.split('.').first]
|
26
|
-
login = ci.delete('login')
|
27
|
-
ref = '%s-reference' % login['application']
|
28
|
-
environments = login.delete('environments')
|
29
|
-
|
30
|
-
ci['reference'] = login.clone
|
31
|
-
ci['reference']['database'] = ref
|
32
|
-
ci['development'] = login.clone
|
33
|
-
|
34
|
-
environments.each do |e|
|
35
|
-
ci[e] = login.clone
|
36
|
-
end
|
37
|
-
|
38
|
-
File.rename("config/database.yml", "config/database.yml.bak") if File.exists?("config/database.yml")
|
39
|
-
|
40
|
-
File.open('config/database.yml', 'w') do |f|
|
41
|
-
f.write(ci.to_yaml);
|
42
|
-
end
|
43
|
-
|
44
|
-
if File.exists?("config/cms_config.deploy.yml")
|
45
|
-
File.rename("config/cms_config.yml", "config/cms_config.yml.bak") if File.exists?("config/cms_config.yml")
|
46
|
-
copy 'config/cms_config.deploy.yml', 'config/cms_config.yml'
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
task :clean_cache do
|
51
|
-
`rm -f public/javascripts/cache_*.js`
|
52
|
-
end
|
53
|
-
|
54
|
-
task :clean_logdir do
|
55
|
-
`for f in log/* tmp/*; do if [ -f $f ]; then rm $f ; fi; done`
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
namespace :db do
|
61
|
-
Rake::Task['db:structure:dump'].clear_actions()
|
62
|
-
namespace :structure do
|
63
|
-
desc "Dump the database structure to a SQL file"
|
64
|
-
task :dump => :environment do
|
65
|
-
if File.exists?('db/ci_structure.sql')
|
66
|
-
STDERR.puts "CI environment detected: not dumping schema"
|
67
|
-
else
|
68
|
-
abcs = ActiveRecord::Base.configurations
|
69
|
-
DatabaseOperations.dump_database_schema!(abcs['development'], 'db/development_structure.sql')
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
Rake::Task['db:test:clone_structure'].clear_actions()
|
75
|
-
namespace :test do
|
76
|
-
desc "Recreate the test databases from the development structure"
|
77
|
-
task :clone_structure => [ "db:structure:dump", "db:test:purge"] do
|
78
|
-
abcs = ActiveRecord::Base.configurations
|
79
|
-
if File.exists?('db/ci_structure.sql')
|
80
|
-
STDERR.puts "CI environment detected"
|
81
|
-
DatabaseOperations.load_database_schema!(abcs['test'], 'db/ci_structure.sql')
|
82
|
-
else
|
83
|
-
DatabaseOperations.load_database_schema!(abcs['test'], 'db/development_structure.sql')
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
data/lib/rf_filtering.rb
DELETED
@@ -1,64 +0,0 @@
|
|
1
|
-
# Include this from application.rb and call rf_param_filtering() with a
|
2
|
-
# whitelist and a blacklist set of params, as below. Blacklisted parameters
|
3
|
-
# are filtered first by Rails, and any other parameters not in the whitelist
|
4
|
-
# are filtered by this code.
|
5
|
-
#
|
6
|
-
## application.rb:
|
7
|
-
#
|
8
|
-
# require 'rf_filtering'
|
9
|
-
# ...
|
10
|
-
# class Application < Rails::Application
|
11
|
-
# ...
|
12
|
-
# include RFFiltering
|
13
|
-
# RFFiltering.UnfilteredEnvironments << 'unfiltered_environment'
|
14
|
-
# rf_param_filtering(
|
15
|
-
# :blacklist => %w[password card_number card_number],
|
16
|
-
# :whitelist => %w[brochure_nickname id])
|
17
|
-
#
|
18
|
-
|
19
|
-
module RFFiltering
|
20
|
-
extend ActiveSupport::Concern
|
21
|
-
|
22
|
-
UnfilteredEnvironments = ['development']
|
23
|
-
FilteredReplacement = '[+++]'
|
24
|
-
|
25
|
-
included do
|
26
|
-
# this space intentionally left blank
|
27
|
-
end
|
28
|
-
|
29
|
-
module ClassMethods
|
30
|
-
attr_reader :rf_filtering_blacklist, :rf_filtering_whitelist
|
31
|
-
|
32
|
-
# Leaving this exposed for mockability
|
33
|
-
def should_filter_params?
|
34
|
-
# there are not a few non-positives in this code.
|
35
|
-
!UnfilteredEnvironments.include?(Rails.env)
|
36
|
-
end
|
37
|
-
|
38
|
-
protected
|
39
|
-
def rf_param_filtering(options = {})
|
40
|
-
@rf_filtering_blacklist = (options[:blacklist] || []).map(&:to_s)
|
41
|
-
@rf_filtering_whitelist = (options[:whitelist] || []).map(&:to_s).to_set
|
42
|
-
|
43
|
-
config.filter_parameters += rf_filtering_blacklist
|
44
|
-
config.filter_parameters << rf_whitelist_filter_proc
|
45
|
-
end
|
46
|
-
|
47
|
-
def rf_whitelist_filter_proc
|
48
|
-
lambda do |k,v|
|
49
|
-
next unless should_filter_params?
|
50
|
-
next unless v.present?
|
51
|
-
next unless v.respond_to?(:to_str) && v.respond_to?(:replace)
|
52
|
-
next if param_filter_white_list.include?(k.to_s)
|
53
|
-
v.replace FilteredReplacement
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
module InstanceMethods
|
59
|
-
# Leaving this exposed for mockability
|
60
|
-
def param_filter_white_list
|
61
|
-
self.class.rf_filtering_whitelist
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
data/lib/sql_obfuscator.rb
DELETED
@@ -1,74 +0,0 @@
|
|
1
|
-
# Include this with an initializer similar to the one below.
|
2
|
-
#
|
3
|
-
# whitelisted_fields = %w[
|
4
|
-
# cached_cms_responses.filename
|
5
|
-
# cached_cms_responses.site
|
6
|
-
# customers.hostname
|
7
|
-
# sessions.session_id
|
8
|
-
# ]
|
9
|
-
# whitelisted_fields.each { |field| SqlObfuscator.whitelist(field) }
|
10
|
-
#
|
11
|
-
# SqlObfuscator.dont_obfuscate_table_and_field do |table, field|
|
12
|
-
# %w[created_at updated_at nickname].include?(field)
|
13
|
-
# end
|
14
|
-
#
|
15
|
-
# NewRelic::Agent.set_sql_obfuscator(:replace) do |sql|
|
16
|
-
# SqlObfuscator.obfuscate(sql)
|
17
|
-
# end
|
18
|
-
#
|
19
|
-
|
20
|
-
|
21
|
-
module SqlObfuscator
|
22
|
-
module_function
|
23
|
-
|
24
|
-
# Provide a facility for whitelisting certain fields
|
25
|
-
WhitelistHash = Hash.new(false)
|
26
|
-
def whitelist(field_expression)
|
27
|
-
WhitelistHash[field_expression] = true
|
28
|
-
end
|
29
|
-
def whitelisted?(field_expression)
|
30
|
-
WhitelistHash[field_expression]
|
31
|
-
end
|
32
|
-
|
33
|
-
DontObfuscateProcs = []
|
34
|
-
# Provides a facility for *not* obfuscating if the field meets some arbitrary criteria.
|
35
|
-
# Takes blocks, calls them on expressions for which a table and field can be found.
|
36
|
-
# Blocks should take two arguments, table and field, and return TRUE if the value should NOT be obfuscated.
|
37
|
-
def dont_obfuscate_table_and_field(&proc)
|
38
|
-
DontObfuscateProcs << proc
|
39
|
-
end
|
40
|
-
|
41
|
-
# Should match:
|
42
|
-
# f_table_name = 'sensitive data'
|
43
|
-
# "some_table"."some_field" = 'sensitive data'
|
44
|
-
# "some_table"."some_field" somehow_matches 'sensitive data'
|
45
|
-
# ...but see also test/unit/lib/sql_obfuscator_unit_test.rb
|
46
|
-
ComparisonExpression = /(?:("\w+"\."\w+")([^"']+)?)?'([^'\\]*((?:\\.|'')[^'\\]+)*)'/
|
47
|
-
|
48
|
-
# Actually do the obfuscation
|
49
|
-
def obfuscate(sql)
|
50
|
-
sql.gsub(ComparisonExpression) do |match|
|
51
|
-
field_expression, comparison, sensitive_data = $1, $2, $3
|
52
|
-
|
53
|
-
# Obfuscate by default
|
54
|
-
obfuscated_sql = [field_expression, comparison, obfuscate_value(sensitive_data)].compact.join
|
55
|
-
|
56
|
-
# Don't obfuscate if we have a field expression that's on the whitelist or is on a 'nickname' field
|
57
|
-
if field_expression.present?
|
58
|
-
table_name, field_name = field_expression.to_s.gsub('"', '').split('.')
|
59
|
-
case
|
60
|
-
when whitelisted?('%s.%s' % [table_name, field_name])
|
61
|
-
obfuscated_sql = match
|
62
|
-
when DontObfuscateProcs.any? { |proc| proc.call(table_name, field_name) }
|
63
|
-
obfuscated_sql = match
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
obfuscated_sql
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def obfuscate_value(value)
|
72
|
-
"'%s'" % Digest::MD5.hexdigest("%d:%s" % [value.to_s.length, value.to_s])
|
73
|
-
end
|
74
|
-
end
|