capistrano-ext-projectdx 0.1.14 → 0.1.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|